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

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;
}

你原来代码的核心坑点

  1. 内存分配半截子工程:你给的createPyramid只写了w = (char**) calloc(dep...,连完整的一级指针分配都没做完,更别说给每一层的字符串分配内存了。直接用没分配的w[i]等于访问野指针,不崩溃才怪,输出随机字符就是因为读了不属于你的内存。
  2. 字符串没加终止符:就算你给字符串分配了内存,要是没加'\0',printf("%s")会一直读内存直到碰到0,这就会输出一堆乱码,甚至触发内存越界崩溃。
  3. 没做错误处理:calloc/malloc可不是每次都能成功,万一内存不足返回NULL,你直接用的话就是空指针解引用,必崩。
  4. 潜在内存泄漏:如果中间某一层字符串分配失败,之前已经分配的内存没释放,就会永久留在内存里,造成泄漏。

敲黑板的注意事项

  • 双指针释放顺序不能乱:必须先释放每个二级指针(w[i]),再释放一级指针(w),反过来的话,释放w之后再访问w[i]就是野指针,又是崩溃风险。
  • calloc比malloc省点事:calloc会自动把内存初始化为0,所以字符串的终止符不用手动加;要是用malloc,一定要记得在字符串末尾补'\0'。
  • 分配失败要回滚:一旦中间分配失败,必须把之前成功分配的内存全部释放,不然就会留下内存泄漏的尾巴。

内容的提问来源于stack exchange,提问作者Jarosław Tomczyński

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:22:47