C语言跨函数调用free()释放calloc创建的结构体数组时崩溃
问题原因
你遇到的错误码0xC0000374是Windows系统定义的堆损坏错误,本质是内存操作越界破坏了堆内存的管理元数据,free执行时检测到堆结构异常直接触发崩溃,核心诱因有两个:
calloc分配内存时的元素大小计算完全错误
原代码中写的是sizeof(propositions),但propositions是函数入参,类型是proposition*(结构体指针),所以这里算出来的大小是指针本身的长度(32位系统下4字节、64位系统下8字节),远小于单个proposition结构体的实际大小。后续往matches数组里写入完整结构体时,会直接超出分配的内存边界,覆盖堆的管理信息,最终导致free崩溃。strcmp返回值判断存在语义错误strcmp匹配相等时返回整数值0,而NULL是空指针常量,虽然数值上两者可能都为0,但把整数返回值和指针常量比较属于不规范写法,存在跨平台/编译环境下的逻辑隐患。
修复方案
按以下两点修改代码即可解决问题:
- 修正
calloc的大小参数:将sizeof(propositions)替换为sizeof(proposition),更稳妥的写法是用sizeof(*matches),后续即使指针类型调整也不会出现大小计算错误。 - 修正字符串比较的判断条件:将所有
strcmp(...) == NULL改为strcmp(...) == 0,符合C标准库函数的语义要求。
修正后的核心代码片段:
proposition* get_matching_propositions(char *pcde, proposition *propositions, int *match_count) { proposition *matches; int count = get_count_from_stream(ptf_proposition, sizeof(proposition)), cptr_match = 0; for (int i = 0; i < count; i++) { if (strcmp(propositions[i].cde, pcde) == 0) { cptr_match++; } } matches = (proposition*) calloc (cptr_match, sizeof(proposition)); assert(matches != NULL); cptr_match = 0; for (int i = 0; i < count; i++) { if (strcmp(propositions[i].cde, pcde) == 0) { matches[cptr_match] = propositions[i]; cptr_match++; } } *match_count = cptr_match; return matches; }
修改后分配的内存大小和实际存储需求完全匹配,不会出现越界写堆的问题,free即可正常执行。
内容的提问来源于stack exchange,提问作者blackberry128
相关产品推荐
相关产品推荐

