You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

参照CS50第5讲使用realloc扩容数组输出随机数问题

代码错误原因排查

代码中共有3处核心逻辑错误,直接触发未定义行为,导致前三个元素读取到随机垃圾值:

  • 空指针判断对象错误
    调用realloc后需要校验的是它的返回值tmp是否为NULL(realloc分配失败时返回空指针),原代码错误判断了旧指针list,等于完全没做realloc的失败校验。
  • 错误手动释放旧指针list
    realloc本身已经封装了完整的内存调整逻辑:如果原内存块后方有足够连续空间,会直接在原地址扩展内存,返回值和旧指针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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 16:27:21