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

释放三级指针时遇double free错误:仅n为奇数时触发的问题排查

问题分析与修复方案

嘿,这个bug我太熟了!你遇到的奇偶n差异报错,根源其实是代码里两个容易被忽略的多余分号,跟奇偶本身没关系——只是奇数n的时候刚好触发了内存检测的错误,偶数时暂时“蒙混过关”而已。

问题出在哪?

看你代码里的这两段循环:

// 第一个嵌套循环
for(j=0; j<n; j++); 
{ 
    (*((*(a + i))+j)) = (uint*) malloc(1 * sizeof(uint)); 
}

// 第二个嵌套循环
for(j=0; j<n; j++); 
{ 
    free (*((*(a + i))+j)); 
}

注意到for循环后面的那个分号;了吗?这个分号会让循环的主体变成空语句——也就是说,循环只是单纯地把j从0递增到n,什么实际操作都没做。等循环结束后,j的值已经是n了(因为当j等于n时,j<n的条件不成立,循环终止)。

这时候你再去访问(*(a+i))+j(也就是a[i][j]),但你给a[i]分配的是n个uint*的空间,下标范围是0到n-1,这就属于数组越界访问了!

为什么奇数n会报错?这是内存分配的随机性导致的:

  • 当n是偶数时,越界的位置可能刚好落在malloc分配的内存块后面的空闲区域,暂时没破坏内存管理的内部结构,所以free时没触发错误;
  • 当n是奇数时,越界的位置刚好覆盖了malloc用来标记内存块大小、下一块地址等的内部数据,free的时候检测到内存结构被破坏,就抛出了“double free or corruption”的错误。

本质上不管n是奇是偶,代码都是有问题的,只是报错的时机不同而已。

修复后的代码

把那两个多余的分号去掉就行,另外建议用数组下标语法代替指针算术,代码更易读:

#include<stdio.h> 
#include<stdlib.h> 
typedef unsigned int uint; 

int main(void) { 
    int i, j; 
    uint n = 3; 
    uint*** a = (uint***) malloc(n * sizeof(uint**)); 

    for(i=0; i<n; i++) { 
        a[i] = (uint**) malloc(n * sizeof(uint*)); 
        for(j=0; j<n; j++) { 
            a[i][j] = (uint*) malloc(sizeof(uint)); 
        } 
    } 

    for(i=0; i<n; i++) { 
        for(j=0; j<n; j++) { 
            free(a[i][j]); 
        } 
        free(a[i]); 
    } 

    free(a); 
    return 0; // 加上return符合C标准规范
}

额外建议

  • 尽量用a[i][j]这种数组下标写法,比指针算术*((*(a + i))+j)可读性高太多,也不容易出错;
  • 可以在malloc后加个空指针检查,避免内存分配失败导致的后续错误,比如:
    if (a == NULL) { /* 处理内存分配失败 */ }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:38:28