
正文
1
bug
大家先不看后面的解析,读一遍代码看能不能立马看出这段代码潜在的风险:
#include<stdio.h>structperson {constchar *name;int id;};staticconststructpersonemployees[] = { {"bug1", 1001}, {"bug2", 1002}, {"bug3", 1003},};voidprint_employees(void){structperson *p = (structperson *)employees;while (p->name != NULL) {printf("Employee: %s (ID: %d)\n", p->name, p->id); p++; }}intmain(void){ print_employees();return0;}2
分析
编写者期望当p->name为NULL时循环终止。然而,由于数组末尾没有显式的终止标志,循环将有可能越过数组边界,继续访问数组之后的内存区域大概率会崩溃,然而当恰巧遇到值为0的内存位置,循环意外终止,运行正常。
其实回味起来感觉就是挺简单的,正常情况下都自信满满不会写出这种的代码,但实际我在多份代码中都有遇到类似的问题。
要改这个问题当然就很简单了,显式的增加终止标志,行业内专业一点的叫法叫做哨兵元素,养成习惯了一般不会出问题。
staticconststructpersonemployees[] = { {"bug1", 1001}, {"bug2", 1002}, {"bug3", 1003}, {NULL, 0} // 明确的终止标志};也通常推荐大家再类似编程的时候,使用数组长度来进行管控,如:
voidprint_employees(void){int count = sizeof(employees) / sizeof(employees[0]);for (int i = 0; i < count; i++) {printf("Employee: %s (ID: %d)\n", employees[i].name, employees[i].id); }}最后
好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个赞~
唯一、永久、免费分享嵌入式技术知识平台~
推荐专辑点击蓝色字体即可跳转
☞ MCU进阶专辑

☞ 专辑|手撕C语言
☞ 专辑|经验分享
