参照CS50第5讲使用realloc扩容数组输出随机数问题
代码错误原因排查
代码中共有3处核心逻辑错误,直接触发未定义行为,导致前三个元素读取到随机垃圾值:
- 空指针判断对象错误
调用realloc后需要校验的是它的返回值tmp是否为NULL(realloc分配失败时返回空指针),原代码错误判断了旧指针list,等于完全没做realloc的失败校验。 - 错误手动释放旧指针
listrealloc本身已经封装了完整的内存调整逻辑:如果原内存块后方有足够连续空间,会直接在原地址扩展内存,返回值和旧指针list完全相同;如果原位置空间不足,会自动申请新的足够大的内存块,拷贝原有数据后自动释放旧内存块。两种场景下都不需要手动调用free(list)。
原代码手动释放list的操作,要么触发重复释放(double free),要么直接释放正在使用的有效内存,后续访问这块内存就属于未定义行为,读到的就是内存中残留的随机值。你看到最后一个元素4能正常输出,是因为free仅标记内存为可重用状态,不会立刻擦除内存内容,刚写入的4暂时残留在对应位置,属于偶然现象,不代表代码逻辑正确。 - 冗余的空指针释放逻辑
当最开始的malloc返回NULL时,说明内存申请失败,此时list本身就是空指针,free(NULL)是C标准定义的无操作,这行释放代码完全冗余,没有实际作用。
修正后的可运行代码
#include <stdio.h> #include <stdlib.h> int main(void){ int *list = malloc(3 * sizeof(int)); if (list == NULL) { return 1; } list[0] = 1; list[1] = 2; list[2] = 3; // 调整数组大小为可存储4个int int *tmp = realloc(list, 4 * sizeof(int)); // 正确校验realloc返回值 if (tmp == NULL) { // 分配失败时释放原有内存再退出 free(list); return 1; } tmp[3] = 4; // 用新指针覆盖旧指针即可,无需手动释放旧内存 list = tmp; // 打印数组内容 for (int i = 0; i < 4; i++) { printf("%i\n", list[i]); } // 最终释放内存 free(list); return 0; }
关键注意点
调用
realloc时不要手动释放传入的旧指针,否则大概率触发内存错误;另外永远要校验realloc的返回值,不要直接把返回值赋值给原指针,否则分配失败时原指针会被置为NULL,造成原有内存泄漏。
内容的提问来源于stack exchange,提问作者zixuan zhu
相关产品推荐
相关产品推荐

