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**,属于类型不兼容的未定义行为,虽然不是这次崩溃的直接诱因,但也存在潜在风险。
修复方案
只需要做两处调整即可解决问题:
- 将初始化、释放两个循环的终止条件从
i <= total改为i < total,保证所有内存访问都落在申请的合法范围内,循环次数和申请的指针个数完全匹配。 - 统一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
相关产品推荐
相关产品推荐

