我的代码:
#include<stdio.h>
#include<stdlib.h>
#include<cs50.h>
int main(void)
{
char *name = malloc(50 * sizeof(char));
if(!name)
{
printf("Memory allocation problem.\n");
return 1;
}
name = get_string("Enter your name: ");
printf("Hello, %s\n", name);
free(name);
}
输出:
Enter your name: dog
Hello, dog
*** Error in `malloc0': double free or corruption (fasttop): 0x0000000001084050 ***
我无法理解我错了,这是一个非常简单的代码,可以将打印名称命名,但是将名称存储在堆内存中。
我只执行一次free()
,但是为什么会出现两次免费错误?
请有人帮助我理解问题。
答案 0 :(得分:4)
cs50自动管理自己的内存。
在主libcs50在cs.50:449中注册atexit
回调之前:
/**
* Called automatically before execution enters main.
*/
INITIALIZER(setup)
{
// Disable buffering for standard output
setvbuf(stdout, NULL, _IONBF, 0);
atexit(teardown);
}
teardown()
函数释放由libcs50分配的所有内存:
static void teardown(void)
{
// Free library's strings
if (strings != NULL)
{
for (size_t i = 0; i < allocations; i++)
{
free(strings[i]);
}
free(strings);
}
}
strings
是cs50.c:67中的全局对象。
当您free(name)
时,名称后面的指针也存储在strings[0]
中(分配给in get_string()
)。
退出main()
后,将执行atexit
注册的回调,并执行free(strings[0])
,试图将对象释放两次。
答案 1 :(得分:3)
根据get_string的描述:
提示用户输入标准输入的文本行,并将其作为字符串(char *)返回,不包括尾行。支持CR(\ r),LF(\ n)和CRLF(\ r \ n)作为行尾。将字符串存储在堆上,但是库的析构函数释放程序出口处的内存。提示符的格式类似于printf(3)。
因此您可以看到它还可以在退出时将其从堆中释放出来。