释放临时Student结构体后,复制的结构体内容发生变化问题咨询
问题根源:浅拷贝导致的内存引用失效
嘿,这个坑我踩过好多次了!你遇到的问题本质上是浅拷贝 vs 深拷贝的典型问题——我来给你拆解清楚:
为什么释放临时结构体后内容会变?
假设你的Student结构体是这样定义的(大概率是用了字符指针):
typedef struct Student { char *first_name; char *surname; int age; } Student;
当你用malloc创建临时的Student* new,然后把输入的in_fname、in_sname直接赋值给new->first_name和new->surname时,你只是把指针地址复制过去了,而不是字符串的实际内容。如果之后你把这个临时结构体的字段直接复制到二叉树节点里,相当于二叉树节点的字符串指针和临时结构体的指针指向同一块内存。
当你free(new)时(如果字符串内存是和结构体绑定的,或者in_fname/in_sname是栈上的临时缓冲区),这块内存会被操作系统回收或覆盖,二叉树里的指针就变成了“野指针”,指向的内容自然就乱了。
两种解决方案,按需选择
方案1:深拷贝字符串内容(推荐用指针结构体的场景)
不要直接复制指针,而是给每个字符串单独分配内存,把实际内容拷贝进去。可以用标准库的strdup(或者自己实现兼容版本):
// 创建临时结构体并赋值 Student* new = malloc(sizeof(Student)); if (!new) { /* 处理内存分配失败 */ } // 深拷贝名字字符串 new->first_name = strdup(in_fname); new->surname = strdup(in_sname); new->age = in_age; // 复制到二叉树节点时,同样做深拷贝 tree_node->student.first_name = strdup(new->first_name); tree_node->student.surname = strdup(new->surname); tree_node->student.age = new->age; // 释放临时结构体时,要先释放字符串内存,再释放结构体本身 free(new->first_name); free(new->surname); free(new);
如果你的环境不支持strdup(比如某些嵌入式编译器),可以自己实现一个:
char* my_strdup(const char* s) { if (!s) return NULL; size_t len = strlen(s) + 1; char* res = malloc(len); if (res) strcpy(res, s); return res; }
方案2:用固定长度字符数组替代指针(更简单的场景)
如果你的名字长度有明确上限,可以把结构体改成字符数组形式,这样赋值时会自动做值拷贝:
#define MAX_NAME_LEN 64 typedef struct Student { char first_name[MAX_NAME_LEN]; char surname[MAX_NAME_LEN]; int age; } Student;
然后赋值时用strncpy保证安全:
Student* new = malloc(sizeof(Student)); strncpy(new->first_name, in_fname, MAX_NAME_LEN - 1); new->first_name[MAX_NAME_LEN - 1] = '\0'; // 确保字符串终止 strncpy(new->surname, in_sname, MAX_NAME_LEN - 1); new->surname[MAX_NAME_LEN - 1] = '\0'; new->age = in_age; // 复制到二叉树节点时,直接用memcpy或者字段赋值 memcpy(&tree_node->student, new, sizeof(Student)); // 直接释放临时结构体即可,不用额外处理字符串 free(new);
额外提醒
不管用哪种方案,记得在销毁二叉树的时候,要对应释放内存:
- 如果用指针方案,要先释放每个节点的
first_name和surname,再释放节点本身; - 如果用数组方案,直接释放节点结构体就行。
内容的提问来源于stack exchange,提问作者Weaver
相关产品推荐
相关产品推荐

