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

使用free释放嵌套struct导致程序崩溃,求问题排查分析

C语言嵌套结构体内存管理崩溃问题分析与修复

你的程序只输出Sucess1就终止,核心原因是指针传递方式错误导致的野指针访问,后续代码根本没机会执行。下面逐一拆解问题并给出修复方案:

1. 致命错误:Init函数的指针传值问题

C语言参数传递是值传递,你在Init中接收的struct Outer *outer是main函数中outer指针的副本。当你执行outer = (struct Outer*) malloc(sizeof(struct Outer));时,仅修改了副本的地址,main里的原始outer指针依然是未初始化的野指针。

这导致main里调用Init后,执行outer->Var = 1时直接访问非法内存,程序瞬间崩溃,根本走不到Exit函数。

2. Exit函数的逻辑错误(次要但需修正)

即便Init函数正常工作,Exit里也存在多处问题:

  • 判断if(outer != NULL)却打印"outer is null",逻辑完全颠倒;
  • free(outer)后还去判断outer != NULL || outer->inner != NULL,此时outer是悬空指针,访问它的成员属于未定义行为;
  • 进入outer->inner != NULL分支时打印"inner is null",内容与逻辑矛盾。

3. 内存分配检查顺序错误

Init里先分配outer和inner再检查空指针,若outer分配失败得到NULL,后续执行outer->inner = malloc(...)会直接访问NULL指针触发崩溃。正确顺序应该是先分配outer,检查成功后再分配inner。


修复后的完整代码

#include <stdio.h>
#include <stdlib.h>

struct Outer
{
    int Var;
    struct Inner
    {
        int Var;
    }*inner;
};

// 改用指针的指针修改main中的原始指针
int Init(struct Outer **outer)
{
    *outer = (struct Outer*) malloc(sizeof(struct Outer));
    if(*outer == NULL){
        printf("fail1: outer malloc failed\n");
        return 1;
    }
    (*outer)->inner = (struct Inner*) malloc(sizeof(struct Inner));
    if((*outer)->inner == NULL){
        printf("fail1: inner malloc failed\n");
        free(*outer); // 分配失败时释放已分配的outer,避免内存泄漏
        return 1;
    }
    printf("Sucess1\n");
    return 0;
}

int Exit(struct Outer *outer)
{
    if(outer != NULL)
    {
        printf("outer is not null\n");
        if(outer->inner != NULL)
        {
            printf("inner is not null, freeing inner\n");
            free(outer->inner);
            outer->inner = NULL; // 置空避免悬空指针
        }
        free(outer);
        outer = NULL;
    }
    
    printf("Sucess2\n");
    return 0;
}

int main()
{
    struct Outer *outer = NULL; // 初始化指针为NULL,避免野指针

    if(Init(&outer) != 0){
        return 1;
    }

    outer->Var = 1;
    outer->inner->Var = 2;

    Exit(outer);

    printf("terminated\n");
    return 0;
}

关键修复点说明

  • Init函数改用struct Outer **outer(指针的指针),直接修改main中原始指针的地址;
  • 调整内存分配检查顺序,分配失败时释放已分配内存,避免泄漏;
  • 修正Exit函数的打印逻辑与悬空指针问题,释放后将指针置空;
  • main中初始化outer为NULL,从根源避免野指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:22:10