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,如果需要做内存清理,这两个字段应当指向堆上动态分配的内存空间。
正确的嵌套结构体清理顺序
清理遵循从内到外,先清理指针指向的动态内存,再清理结构体本身内存的规则,步骤如下:
- 先清理内层结构体中指针指向的动态内存:对
emp->add.city指向的堆内存执行sanitize,再释放该内存 - 再清理外层结构体中指针指向的动态内存:对
emp->name指向的堆内存执行sanitize,再释放该内存 - 清理内层
struct address结构体本身的内存 - 清理外层
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
相关产品推荐
相关产品推荐

