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

C语言调用free前如何清理堆内存?嵌套结构体清理段错误如何解决

问题原因分析
  • 内存分配错误:你为struct employee分配内存时使用了malloc(sizeof(char) * 40),手动指定40字节的方式不可靠,不同平台的结构体对齐规则不同,很容易出现内存越界,正确写法应为malloc(sizeof(struct employee))。
  • 段错误直接诱因:你调用sanitize(&(emp->add), sizeof(struct address))时,直接将struct address结构体本身的内存全部覆写为0xAA,而struct address中的city是指针类型,覆写后指针值变为非法的0xAA,后续printf("%s\n", emp->add.city)尝试访问0xAA地址的内存,属于非法访问,直接触发段错误。
  • 字符串存储位置错误:你当前的name和city指针指向的是字符串常量,存储在只读数据段,本身既不能被覆写也不能被free,如果需要做内存清理,这两个字段应当指向堆上动态分配的内存空间。
正确的嵌套结构体清理顺序

清理遵循从内到外,先清理指针指向的动态内存,再清理结构体本身内存的规则,步骤如下:

  1. 先清理内层结构体中指针指向的动态内存:对emp->add.city指向的堆内存执行sanitize,再释放该内存
  2. 再清理外层结构体中指针指向的动态内存:对emp->name指向的堆内存执行sanitize,再释放该内存
  3. 清理内层struct address结构体本身的内存
  4. 清理外层struct employee结构体本身的内存,最后释放emp指向的堆空间
修正后的代码示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct address{
    char *city;
    int zip;
};

struct employee{
    char *name;
    struct address add;
};

void sanitize(char *ptr, int size){
    memset(ptr, 0xAA, size);
}

int main()
{
    struct employee* emp;
    // 按结构体实际大小分配内存
    emp = malloc(sizeof(struct employee));
    // 使用堆分配的字符串,替代只读区的字符串常量,方便后续清理
    emp->name = malloc(10);
    strcpy(emp->name, "John");
    emp->add.city = malloc(10);
    strcpy(emp->add.city, "London");
    emp->add.zip = 221;

    printf("%s\n", emp->add.city);

    // 按从内到外的顺序清理
    sanitize(emp->add.city, 10);
    free(emp->add.city);
    sanitize(emp->name, 10);
    free(emp->name);
    sanitize(&(emp->add), sizeof(struct address));
    sanitize(emp, sizeof(struct employee));
    free(emp);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:09:02