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

C语言外部函数释放二级指针触发double free报错排查

错误产生原因

核心触发原因是内存越界访问破坏了glibc的内存管理元数据,具体细节:

  • 你给p1申请的内存大小是total * sizeof(char *),也就是只能存放total个char类型指针,合法的访问下标范围是0到total-1。
  • 初始化内存、释放内存的两处循环都用了i <= total作为终止条件,会额外访问下标为total的内存位置——这个位置不在你申请的p1内存块范围内,属于内存管理器保留的元数据存储区域,不属于程序可合法写入的范围。
  • 初始化时给*(p1 + total)赋值的操作,会直接覆盖malloc用来记录内存块大小、空闲状态的内部元数据。后续执行free操作时,内存管理器校验元数据发现数值非法,就会直接抛出double free or corruption (out)错误,终止程序并输出Aborted (core dumped)提示。
  • 另外代码里p1定义为const char**类型,函数返回值却是char**,属于类型不兼容的未定义行为,虽然不是这次崩溃的直接诱因,但也存在潜在风险。
修复方案

只需要做两处调整即可解决问题:

  1. 将初始化、释放两个循环的终止条件从i <= total改为i < total,保证所有内存访问都落在申请的合法范围内,循环次数和申请的指针个数完全匹配。
  2. 统一p1的指针类型和函数返回值类型,消除类型不兼容的隐患。

修复后的完整代码如下:

char **someFunction(){
    // 类型与返回值保持一致
    char ** p1 = (char **)malloc(total * sizeof(char *));
    // 修正循环边界,仅访问0~total-1的合法下标
    for (int i = 0; i < total; i++){
        *(p1 + i) = (char *)malloc(len * sizeof(char) + 1);
    }
    return p1;
}

void free_stuffs(char ** p1){
    // 释放逻辑同步修正循环边界,和分配逻辑一一对应
    for (int i = 0; i < total; i++){
        free(p1[i]);
    }
    free(p1);
}

注意:编写动态数组的分配、释放逻辑时,必须保证循环访问的元素个数和malloc申请的元素个数完全一致,多一次访问就会触发越界写破坏内存结构,少一次访问就会造成内存泄漏。

内容的提问来源于stack exchange,提问作者PYigit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:03:22