在只有一个自由函数的地方获得双重自由

时间:2019-01-07 11:21:04

标签: c cs50

我的代码:

#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(),但是为什么会出现两次免费错误?

请有人帮助我理解问题。

2 个答案:

答案 0 :(得分:4)

cs50自动管理自己的内存。

在主libcs​​50在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()函数释放由libcs​​50分配的所有内存:

static void teardown(void)
{
    // Free library's strings
    if (strings != NULL)
    {
        for (size_t i = 0; i < allocations; i++)
        {
            free(strings[i]);
        }
        free(strings);
    }
}

stringscs50.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)。

因此您可以看到它还可以在退出时将其从堆中释放出来。