嵌入式C中strcpy()函数二次调用陷入死循环问题求助
嘿,我来帮你排查这个嵌入式C里的strcpy死循环问题——你的代码里有几个关键错误,叠加起来导致了第二次调用时的异常,咱们一个个拆解:
1. 内存释放的致命错误
你最后直接写了free(_Items);,但要注意:_Items是栈上分配的指针数组(char *_Items[100];),它根本不是用malloc动态分配的内存!真正需要释放的是每个_Items[count]指向的堆内存——这些才是你循环里用malloc申请的。
正确的释放逻辑应该是这样:
// 逐个释放每个动态分配的字符串内存 for(count=0; count<10 ; count++) { if(_Items[count] != NULL) { free(_Items[count]); _Items[count] = NULL; // 置空避免野指针 } } // 不用free(_Items),它在栈上,函数返回时会自动销毁
第一次调用后没正确释放,会造成内存泄漏,堆内存要么被耗尽,要么堆结构被破坏。第二次调用malloc时很可能拿到非法指针,strcpy操作这些内存时,就会出现不可预料的行为——比如死循环,因为找不到字符串终止符'\0'。
2. 变量名的笔误大坑
你代码里定义了unsigned char contactname[36];,但后面却写了Memset(name,0,36);——这个name变量是哪里来的?如果是笔误应该写成contactname,那未初始化的name会导致strlen((char*)name)越界读取内存,算出错误的长度,malloc出来的内存不够用,strcpy直接溢出破坏堆结构,这也是后续调用异常的重要原因。
3. 字符串终止符的隐患
如果name(或者正确的contactname)不是以'\0'结尾的,strlen会一直读内存直到碰到'\0',导致malloc分配的内存大小错误。strcpy写入时超出分配的内存,会破坏堆的元数据,进而让第二次调用的malloc/strcpy彻底乱套,甚至触发死循环。
修复后的代码参考
char *_Items[100]; unsigned char contactname[36]; int count; // 初始化contactname(注意变量名要对应) memset(contactname, 0, sizeof(contactname)); // 把指针数组全部置为NULL,避免野指针 memset(_Items, 0, sizeof(_Items)); // 这里假设你会给contactname赋值,比如从外设读取或者其他逻辑 // strcpy((char*)contactname, "test_contact"); for(count=0; count<10 ; count++) { // 先确保字符串是合法的(以'\0'结尾) size_t name_len = strlen((char*)contactname); // sizeof(char)固定是1,不用乘,节省代码 _Items[count] = (char*)malloc(name_len + 1); if(_Items[count] == NULL) { // 嵌入式环境一定要处理内存分配失败的情况,比如退出循环或者报错 break; } strcpy(_Items[count], (char*)contactname); } // ... 函数其他业务逻辑 ... // 退出前正确释放内存 for(count=0; count<10 ; count++) { if(_Items[count] != NULL) { free(_Items[count]); _Items[count] = NULL; } }
额外的嵌入式编程小建议
- 尽量用
strncpy替代strcpy,指定最大复制长度,能有效避免溢出:strncpy(_Items[count], (char*)contactname, name_len);,记得手动加终止符_Items[count][name_len] = '\0'; - 每次
malloc后必须检查返回值是否为NULL,嵌入式内存资源有限,分配失败是常见情况 - 变量名一定要仔细核对,笔误在嵌入式里很容易导致难以排查的硬错误
内容的提问来源于stack exchange,提问作者Shreevatsa Y S

