也许是一个糟糕的主题,但鉴于以下代码,我是否也需要free(player->name)
?
#include <stdio.h>
struct Player
{
char *name;
int level;
};
int main()
{
struct Player *player;
player->name = malloc(sizeof(player->name)*256);
player->name = "John";
printf(player->name);
free(player);
printf("\n\n\n");
system("PAUSE");
return 0;
}
答案 0 :(得分:15)
哦,小伙子,从哪里开始?你真的需要一本好书。叹。让我们从main()
的顶部开始:
此
struct Player *player;
定义了指向struct Player
的指针,但它没有初始化它。因此它具有或多或少的随机值,指向存储器中的某处。此
player->name = malloc(sizeof(player->name)*256);
现在将malloc()
获得的一块内存的地址写入该随机位置的部分内容。通过未初始化的指针写入内存会调用未定义的行为。之后,所有赌注都已关闭。无需进一步了解您的计划。你不幸的是,你不小心写入了你的进程所拥有的一块内存,所以它不会立即崩溃,让你意识到这个问题。
有两种方法可以改善这种状况。要么坚持指针并让它指向为Player
对象分配的一块内存。你可以致电malloc(sizeof(Player)
来获得它
或者只使用本地的自动(也就是基于堆栈的)对象:
struct Player player;
编译器将生成代码以在堆栈上为其分配内存并自动释放它。这是最简单的,当然应该是你的默认值。
但是,您的代码存在更多问题。
此
player->name = malloc(sizeof(player->name)*256);
在堆上分配连续内存以存储256个指向字符的指针,并分配第一个指针的地址(char*
的地址,因此为char**
)至player->name
(a char*
)。坦率地说,我很惊讶甚至编译,但后来我更习惯于C ++更严格的类型执行。无论如何,你可能想要的是为256个字符分配内存:
player->name = malloc(sizeof(char)*256);
(根据定义,sizeof(char)
是1
,您通常会将其视为malloc(256)
。)
但是,还有更多:为什么256?如果我将字符串传递1000个字符怎么办?不,简单地为更长的字符串分配空间不是解决这个问题的方法,因为我可以将它传递给更长的字符串。所以 1)修复了最大字符串长度(只需将Player::name
声明为该长度的char
数组,而不是char*
)并强制执行此限制在您的代码中,或 2)在运行时动态查找所需的长度,并准确分配所需的内存(字符串长度加1,终止'\0'
char)。
但它变得更糟。此
player->name = "John";
然后将字符串文字的地址分配给player->name
,覆盖malloc()
在您存储的唯一变量中分配的内存地址,使您丢失并泄漏内存。 />
但是字符串在C中不是一等公民,所以你不能分配它们。它们是字符数组,按惯例终止为'\0'
。要复制它们,您必须逐个字符地复制它们,或者最好是通过调用strcpy()
来复制它们。
为了增加对伤害的侮辱,你后来尝试释放字符串文字所在的记忆
free(player);
因此很可能严重扰乱堆管理器的数据结构。同样,你似乎不幸的是不会导致立即崩溃,但代码看似按预期工作是未定义行为表现自己的最糟糕可能性之一。如果以前所有赌注都没有被淘汰,他们现在就会完全失败。
我很抱歉,如果这听起来有点谴责,那真的不是那种意思,但你肯定并且认真地搞砸了这个。总结一下:
你需要一本好的C ++书。马上。 Here是C程序员在Stack Overflow上汇编的好书。 (我是一名C ++程序员,所以我不会评论他们的判断,但K&amp; R肯定是一个不错的选择。)
您应该立即初始化所有指针,使用现有有效对象的地址,或者使用分配用于保存正确类型对象的内存块的地址,或使用NULL
(您可以在以后轻松查看)。特别是,您不得尝试读取或写入尚未分配(在堆上动态或在堆栈上自动分配)的内存。
您需要free()
通过恰好调用malloc()
一次获得的所有内存。
您不得尝试free()
任何其他记忆。
我确信该代码还有更多内容,但我会在这里停下来。 我是否提到你需要一本好的C书?因为你这样做了。
答案 1 :(得分:0)
player
不需要被释放,因为它永远不会malloc
',它只是一个本地堆栈变量。确实需要释放player->name
,因为它是动态分配的。
int main()
{
// Declares local variable which is a pointer to a Player struct
// but doesn't actually point to a Player because it wasn't initialised
struct Player *player;
// Allocates space for name (in an odd way...)
player->name = malloc(sizeof(player->name)*256);
// At this point, player->name is a pointer to a dynamically allocated array of size 256*4
// Replaces the name field of player with a string literal
player->name = "John";
// At this point, the pointer returned by malloc is essentially lost...
printf(player->name);
// ?!?!
free(player);
printf("\n\n\n");
system("PAUSE");
return 0;
}
我想你想做这样的事情:
int main() {
struct Player player;
player.name = malloc( 256 );
// Populate the allocated memory somehow...
printf("%s", player.name);
free(player.name);
}
答案 2 :(得分:0)
您必须free()
malloc()
所有内容,并且必须malloc()
在编译时未分配的所有内容。
所以:
您必须使用malloc player
并且必须免费player->name
答案 3 :(得分:0)
好的,所以你的变量播放器是一个你没有初始化的指针,因此指向一个随机的内存位置。
首先需要为player
分配内容player->name
,然后为播放器&gt;名称分配内容。
分配有malloc()
的任何内存都需要使用free()
释放。
答案 4 :(得分:0)
这是糟糕的代码。为什么?首先,为player-&gt; name分配内存。 malloc返回指向已分配内存的指针。在下一步中,您将丢失此指针值,因为重新分配player-&gt; name以指向静态“John”字符串。也许你想使用strdup或sprintf函数?
同样最大的错误是使用未初始化的指针指向播放器结构。试着想象它可以指向随机内存位置。所以在malloc的帮助下为你的结构分配内存是个好主意。或者不要使用指针来构造并使用真实的结构变量。