复制结构的内容在临时结构为 `free` d 后发生变化
Contents of copied structure changes after temporary structure is `free` d
我正在制作一个简单的数据库程序来学习结构和二叉树。我创建了一个包含 3 个字段的全局结构 Student
:名字、姓氏、年龄,并编写了一个函数来获取 3 个用户输入(存储为字符串 in_fname
、in_sname
和 int in_age
,比方说)并将它们放入临时结构 new
,并计划将它们复制到主树的适当位置。在获取第一个条目的用户输入后,我有:
struct Student *new;
new = (Student *) malloc (sizeof(struct Student));
strcpy (new->fname, in_fname);
strcpy (new->sname, in_sname);
new->age = in_age;
new->left = new->right = NULL;
printf("Contents of new is '%s', '%s', '%d'.\n",new->fname, new->sname, new->age);
student_tree = new /* wanting to copy the new student as the first entry in the tree*/
现在当我
print("Contents of structure is '%s', '%s', '%d'.\n",student_tree->fname, student_tree->sname, student_tree->age);
我得到了正确的条目,表明复制成功了,但是当我
free(new)
print("Contents of structure is '%s', '%s', '%d'.\n",student_tree->fname, student_tree->sname, student_tree->age);
(认为它是临时的,我不再需要它了)当我的第一个条目 fname
总是损坏,包含垃圾。
有人可以解释一下我缺少什么吗?不一定要固定的代码,只是为了理解为什么当我从中复制的东西消失时树中的结构内容会发生变化,以及如何永久复制它。
非常感谢,
W
因为student_tree
和new
是指针。当你将new
赋值给student_tree
时,没有复制,它只是让student_tree
指向同一个内存。当你调用 free(new)
时,它会回收 new
指向的内存,这也是 student_tree
指向的内存,所以它是垃圾是可以理解的。
下面是一些可以进行实际复制的代码:
struct Student* student_tree = malloc(sizeof(struct Student));
*student_tree = *new;
这里我创建了指针student_tree
,分配内存来存放struct Student
,最后将new
指向的内存中的内容放到new
指向的内存中student_tree
.
执行 free(now)
然后稍后访问 now
就像关掉你的引擎,然后想知道为什么你的车在你踩下油门踏板时不再加速。
注意
student_tree = new
是不是复制new
指向的内容,只是赋值
另一个指向 new
指向的位置的指针。你这里有什么
只是指向同一位置的 2 个指针。如果你这样做 free(now)
,那么
两个指针都指向释放的内存,当然你不能访问
具有指针之一的内存(new
或 student_tree
)。
如果你想释放new
,那么你必须复制内存。这个可以
像这样用 memcpy
完成:
struct Student copy;
memcpy(©, new, sizeof copy);
但取决于结构本身(是否包含指针或数组),
memcpy
可能不是正确的解决方案。
现在很难给你一个正确的答案,因为太多了
您缺少的信息,例如 struct Person
的样子,如何插入
函数的外观、您如何称呼它们等等
还有
strcpy (new->fname, in_fname);
strcpy (new->sname, in_sname);
这可能很危险,您没有给我们足够的信息,但是如果您
一不小心,您可能会溢出缓冲区。我从你的代码中推测
fname
和 sname
都是 char
数组。在那种情况下,我会使用 strncpy
相反,因为可能不知道 in_fname
和 in_sname
的实际长度
and/or 可能比 fname
和 sname
可以容纳的更大。所以一般来说
更强大的解决方案是:
strncpy(new->fname, in_fname, sizeof new->fname);
new->fname[sizeof(new->fname) - 1] = '[=13=]';
strncpy(new->sname, in_sname, sizeof new->sname);
new->sname[sizeof(new->sname) - 1] = '[=13=]';
在您发布的代码中,new
是一个指针,不包含结构 Student
,而是指向 Student
的内存地址。在 C 中,大部分数据可以存储在程序的堆栈内存或堆内存中。堆栈内存是受管理的,但在您退出范围时变得无效,而堆内存在整个程序中都是持久的。 malloc()
根据您的指示分配尽可能多的堆内存(在本例中,足够 Student
)和 returns 指向已分配内存的指针。因为 new
指向的内存在整个程序中都是持久的,所以您必须使用 free()
手动释放内存。
这一行对于理解指针很重要:
student_tree = new;
在不知道 student_tree
的类型的情况下,很难说出发生了什么,但我们假设上面某处存在声明 struct Student *student_tree;
。如果是这种情况,那么这两个变量都是在您的堆栈内存中分配的指针,并且 student_tree
被分配了 new
的值,这是您使用 malloc()
分配的内存地址。
因为两个变量现在都指向同一个内存,当内存被释放时,两个指针都没有指向有效内存。
我正在制作一个简单的数据库程序来学习结构和二叉树。我创建了一个包含 3 个字段的全局结构 Student
:名字、姓氏、年龄,并编写了一个函数来获取 3 个用户输入(存储为字符串 in_fname
、in_sname
和 int in_age
,比方说)并将它们放入临时结构 new
,并计划将它们复制到主树的适当位置。在获取第一个条目的用户输入后,我有:
struct Student *new;
new = (Student *) malloc (sizeof(struct Student));
strcpy (new->fname, in_fname);
strcpy (new->sname, in_sname);
new->age = in_age;
new->left = new->right = NULL;
printf("Contents of new is '%s', '%s', '%d'.\n",new->fname, new->sname, new->age);
student_tree = new /* wanting to copy the new student as the first entry in the tree*/
现在当我
print("Contents of structure is '%s', '%s', '%d'.\n",student_tree->fname, student_tree->sname, student_tree->age);
我得到了正确的条目,表明复制成功了,但是当我
free(new)
print("Contents of structure is '%s', '%s', '%d'.\n",student_tree->fname, student_tree->sname, student_tree->age);
(认为它是临时的,我不再需要它了)当我的第一个条目 fname
总是损坏,包含垃圾。
有人可以解释一下我缺少什么吗?不一定要固定的代码,只是为了理解为什么当我从中复制的东西消失时树中的结构内容会发生变化,以及如何永久复制它。
非常感谢,
W
因为student_tree
和new
是指针。当你将new
赋值给student_tree
时,没有复制,它只是让student_tree
指向同一个内存。当你调用 free(new)
时,它会回收 new
指向的内存,这也是 student_tree
指向的内存,所以它是垃圾是可以理解的。
下面是一些可以进行实际复制的代码:
struct Student* student_tree = malloc(sizeof(struct Student));
*student_tree = *new;
这里我创建了指针student_tree
,分配内存来存放struct Student
,最后将new
指向的内存中的内容放到new
指向的内存中student_tree
.
执行 free(now)
然后稍后访问 now
就像关掉你的引擎,然后想知道为什么你的车在你踩下油门踏板时不再加速。
注意
student_tree = new
是不是复制new
指向的内容,只是赋值
另一个指向 new
指向的位置的指针。你这里有什么
只是指向同一位置的 2 个指针。如果你这样做 free(now)
,那么
两个指针都指向释放的内存,当然你不能访问
具有指针之一的内存(new
或 student_tree
)。
如果你想释放new
,那么你必须复制内存。这个可以
像这样用 memcpy
完成:
struct Student copy;
memcpy(©, new, sizeof copy);
但取决于结构本身(是否包含指针或数组),
memcpy
可能不是正确的解决方案。
现在很难给你一个正确的答案,因为太多了
您缺少的信息,例如 struct Person
的样子,如何插入
函数的外观、您如何称呼它们等等
还有
strcpy (new->fname, in_fname);
strcpy (new->sname, in_sname);
这可能很危险,您没有给我们足够的信息,但是如果您
一不小心,您可能会溢出缓冲区。我从你的代码中推测
fname
和 sname
都是 char
数组。在那种情况下,我会使用 strncpy
相反,因为可能不知道 in_fname
和 in_sname
的实际长度
and/or 可能比 fname
和 sname
可以容纳的更大。所以一般来说
更强大的解决方案是:
strncpy(new->fname, in_fname, sizeof new->fname);
new->fname[sizeof(new->fname) - 1] = '[=13=]';
strncpy(new->sname, in_sname, sizeof new->sname);
new->sname[sizeof(new->sname) - 1] = '[=13=]';
在您发布的代码中,new
是一个指针,不包含结构 Student
,而是指向 Student
的内存地址。在 C 中,大部分数据可以存储在程序的堆栈内存或堆内存中。堆栈内存是受管理的,但在您退出范围时变得无效,而堆内存在整个程序中都是持久的。 malloc()
根据您的指示分配尽可能多的堆内存(在本例中,足够 Student
)和 returns 指向已分配内存的指针。因为 new
指向的内存在整个程序中都是持久的,所以您必须使用 free()
手动释放内存。
这一行对于理解指针很重要:
student_tree = new;
在不知道 student_tree
的类型的情况下,很难说出发生了什么,但我们假设上面某处存在声明 struct Student *student_tree;
。如果是这种情况,那么这两个变量都是在您的堆栈内存中分配的指针,并且 student_tree
被分配了 new
的值,这是您使用 malloc()
分配的内存地址。
因为两个变量现在都指向同一个内存,当内存被释放时,两个指针都没有指向有效内存。