следует ли free () указателям?

Я уверен, что это не так, но, возможно, в этом есть черная магия, поэтому вот мой вопрос:

Если у меня есть такая структура:

struct mystr {
    char * strp,
    unsigned int foo,
};

и я выделяю память для него и хочу выпустить его позже. Должен ли я сделать

free(mystr_var->strp);
free(mystr_var);

или последняя строка достаточно, делает free() функция следуйте указателям и освободите их два?

6 ответов


каждый отдельно выделенный блок памяти должен быть освобожден индивидуально. free() освободит только блок памяти, на который указывает указатель, и не знает, что такое содержимое этой памяти.

следовательно, в вашем случае вы делаете это правильно, сначала освобождая самую внутреннюю память, выделенную в структуре, и, наконец, освобождая указатель структуры.

Если вы просто освободите указатель структуры, память структуры освободится. Память, удерживаемая char* strp, становится утечкой памяти в вашей жизни программы.


нет, free не следует указателям, вам нужны обе строки.

обычно я пишу такую функцию, как:

void freemystr(mystr *mystr_var)
{
    if (mystr_var)
    {
        free(mystr_var->strp);
        mystr_var->strp = NULL;
        free(mystr_var);
    }
}

нет, это не так.

это вообще не магия, для компилятора это просто еще один вызов функции.

спросите себя, как бы вы реализовали void free(void *); таким образом, который следует указателям, конечно, не обманываясь тем, что дается двоичный блок данных, содержащий что-нибудь. Ты не можешь.


нет. Он просто освобождает указанный блок.

вам нужно явно освободить ссылочную память. Вам нужно сделать это первым (т. е. скорее всего в противоположном направлении от того, как вы выделили память)


нет. free не рекурсивный бесплатно для всех пользователей. Вы должны явно освободить все члены, для которых вы выделили память.

если вы понимаете, как выделяется память для struct и как работает free, это не будет проблемой.

struct mystr {
    char * strp,
    unsigned int foo,
};

когда вы выделили память с помощью malloc & friends, он выделяет только память для членов. В вашем случае один char* и unsigned int. Обратите внимание, что он не выделяет память для хранения данных в char*. Таким образом, вы должны выделить память для strp снова перед сохранением данных. За исключением случаев, когда вы напрямую назначаете строковые литералы или просто используете указатель strp чтобы указать на существующую память.

пример:

Пример 1:

struct mystr s;

s.strp = "literals"; // valid, no need to malloc

Пример 2:

char *p="abc";

s.strp = p; // valid, no need to malloc

на всех других использованиях, вы должны выделить память для strp перед сохранением данных в strp.

поэтому, когда вы называете free в переменной struct он освобождает только указатель, выделенный для strp а не память, на которую указывает strp. Это просто потому, что free не имеет информации о том, где strp указывает.

обратите внимание, что в приведенных выше двух примерах вы не освобождаете strp поскольку вы не выделили там никакой памяти для хранения данных в strp. Простое правило-один бесплатно один malloc/calloc/realloc.


C99 говорит,

свободная функция освобождает пространство, на которое указывает ptr, то есть делает его доступным для дальнейшего распределения. Если ptr является нулевым указателем, никаких действий не происходит. В противном случае, если аргумент не соответствует указателю, ранее возвращенному функцией calloc, malloc или realloc, или если пространство было освобождено вызовом free или realloc, поведение не определено.