Получение двойного освобождения, когда только одна функция свободна - PullRequest
0 голосов
/ 07 января 2019

мой код:

#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 голосов
/ 07 января 2019

Из описания get_string:

Запрашивает у пользователя строку текста из стандартного ввода и возвращает ее в виде строки (char *), без завершающего конца строки. Поддерживает CR (\ r), LF (\ n) и CRLF (\ r \ n) как окончания строк. Сохраняет строку в куче, , но деструктор библиотеки освобождает память при выходе из программы . Приглашение отформатировано как printf (3).

так что, как вы видите, он также освобождает его от кучи на выходе.

0 голосов
/ 07 января 2019

CS50 автоматически управляет собственной памятью.

Перед основным libcs50 регистрируется atexit обратный вызов в cs.50: 449 :

/**
 * 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] (присваивается в get_string()).

После выхода main() выполняется зарегистрированный обратный вызов atexit и выполняется free(strings[0]), который пытается освободить объект вдвое.

...