请问如下动态分配内存的二维数组释放代码存在什么错误?如何修复?
动态二维数组内存释放逻辑分析
现有代码可取之处
释放顺序符合规范:先逐行释放每一行的一维数组内存,再释放存储行指针的二级指针内存,遵循了「后申请先释放」的动态内存管理原则,不存在释放顺序颠倒导致的野指针问题。
存在的问题及修复方案
问题1:行内存分配失败时存在内存泄漏
对应问题代码段:
if (NULL == *(pptr + idx)) { printf("ERROR: malloc failed.\n"); exit(1); }
- 错误原因:如果循环到第N行时malloc失败,程序直接退出,前面0~N-1行已经分配成功的内存、以及最开始申请的二级指针
pptr指向的8个int*大小的内存都没有被释放,产生内存泄漏。 - 修复方案:分配失败时,先释放已经申请成功的所有行内存,再释放二级指针
pptr,再退出程序,修改后的分配逻辑如下:
for (idx = 0; idx < 8; idx++) { *(pptr + idx) = (int*)malloc(sizeof(int) * 6); if (NULL == *(pptr + idx)) { printf("ERROR: malloc failed.\n"); // 先释放已分配的行内存 for(int j = 0; j < idx; j++) { free(*(pptr + j)); } free(pptr); // 释放二级指针内存 exit(1); } }
问题2:free后判断指针非空再置空的逻辑错误
对应问题代码段:
free(*(pptr + idx)); if (NULL != *(pptr + idx)) { *(pptr + idx) = NULL; } ... free(pptr); if (NULL != pptr) { pptr = NULL; }
- 错误原因:C标准中
free()函数只会回收指针指向的堆内存,不会修改指针变量本身的取值,调用free后指针仍然指向原来的内存地址(变为野指针),因此NULL != *(pptr + idx)的判断永远为真,属于完全冗余的无效逻辑。 - 修复方案:删除冗余的非空判断,
free后直接将指针置为NULL即可,修改后的释放逻辑如下:
for (idx = 0; idx < 8; idx++) { free(*(pptr + idx)); *(pptr + idx) = NULL; } free(pptr); pptr = NULL;
可选优化建议
C语言中不需要强制转换malloc的返回值,void*可以自动隐式转换为任意指针类型,强制转换反而可能隐藏未引入<stdlib.h>的编译警告。
内容的提问来源于stack exchange,提问作者neue zeal
相关产品推荐
相关产品推荐

