C语言双指针内存泄漏排查:程序崩溃输出乱码原因分析
搞定C语言双指针内存泄漏与崩溃问题
嘿,看你遇到的这个问题——程序崩溃、输出随机字符,还搞不清内存泄漏在哪,结合你给的代码片段,我一眼就瞅出createPyramid函数是重灾区,大概率是内存分配没做完整、字符串没正确终止导致的。先给你补全并修复好代码,再慢慢给你唠清楚问题出在哪:
修复后的完整可运行代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 要用到memset的话得加这个头文件 char** createPyramid(int depth); int main(int argc, char** argv) { printf("\n createPyramid \n"); int depth = 9; char** w = createPyramid(depth); // 先检查金字塔内存分配成功没,别上来就用 if (w == NULL) { fprintf(stderr, "金字塔内存分配失败!\n"); return 1; } for (int i = 0; i < depth; i++){ printf("%s \n", w[i]); } // 释放内存得讲顺序:先放每一层的字符串,再放顶层的指针数组 for (int i = 0; i < depth; i++){ free(w[i]); } free(w); return 0; } char** createPyramid(int depth){ // 第一步:先给顶层指针数组分配内存,存depth个char*类型的指针 char** w = (char**) calloc(depth, sizeof(char*)); if (w == NULL) { return NULL; // 分配失败直接返回,别硬撑 } for (int i = 0; i < depth; i++) { // 第i层(从0开始算)需要i+1个字符,再加上字符串终止符'\0',总共i+2个字节 int str_size = i + 2; // 给每一层的字符串分配内存 w[i] = (char*) calloc(str_size, sizeof(char)); if (w[i] == NULL) { // 要是这层分配失败了,得把之前已经分配好的内存都释放了,不然就泄漏了 for (int j = 0; j < i; j++) { free(w[j]); } free(w); return NULL; } // 填充字符,比如用'*'搭金字塔 memset(w[i], '*', i + 1); // 因为用了calloc,内存会自动初始化为0,所以'\0'已经在末尾了,不用手动加 // 要是用malloc的话,得手动加一句:w[i][i+1] = '\0'; 不然printf会读垃圾内存 } return w; }
你原来代码的核心坑点
- 内存分配半截子工程:你给的
createPyramid只写了w = (char**) calloc(dep...,连完整的一级指针分配都没做完,更别说给每一层的字符串分配内存了。直接用没分配的w[i]等于访问野指针,不崩溃才怪,输出随机字符就是因为读了不属于你的内存。 - 字符串没加终止符:就算你给字符串分配了内存,要是没加
'\0',printf("%s")会一直读内存直到碰到0,这就会输出一堆乱码,甚至触发内存越界崩溃。 - 没做错误处理:
calloc/malloc可不是每次都能成功,万一内存不足返回NULL,你直接用的话就是空指针解引用,必崩。 - 潜在内存泄漏:如果中间某一层字符串分配失败,之前已经分配的内存没释放,就会永久留在内存里,造成泄漏。
敲黑板的注意事项
- 双指针释放顺序不能乱:必须先释放每个二级指针(
w[i]),再释放一级指针(w),反过来的话,释放w之后再访问w[i]就是野指针,又是崩溃风险。 - calloc比malloc省点事:
calloc会自动把内存初始化为0,所以字符串的终止符不用手动加;要是用malloc,一定要记得在字符串末尾补'\0'。 - 分配失败要回滚:一旦中间分配失败,必须把之前成功分配的内存全部释放,不然就会留下内存泄漏的尾巴。
内容的提问来源于stack exchange,提问作者Jarosław Tomczyński
相关产品推荐
相关产品推荐

