Функция free () в C не работает для меня - PullRequest
0 голосов
/ 15 октября 2011

Я пытался освободить память, выделенную через malloc(), используя free().

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

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

Код, который я использую для освобождения памяти:

void FreeMemory(InfoDefiner *InfoCarrier)
{
    if ((*InfoCarrier) != NULL) {
        FreeMemory((&(*InfoCarrier)->left));
        FreeMemory((&(*InfoCarrier)->right));
        free((*InfoCarrier));
    }
}

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

if (gRootPtr != NULL) {
    return 1;
}
else{
    return 0;
}

Ответы [ 5 ]

16 голосов
/ 15 октября 2011

Во-первых, free не меняет указатель .

void *x = malloc(1);
free(x);
assert(x != NULL); // x will NOT return to NULL

Если вы хотите, чтобы указатель вернулся к NULL, вы должны сделать это самостоятельно.

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

int *x = malloc(sizeof(int));
*x = 42;
free(x);
// The vlaue of *x is undefined; it may be 42, it may be 0,
// it may crash if you touch it, it may do something even worse!

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

5 голосов
/ 15 октября 2011

Эта проверка не будет проверять, освобождена ли переменная.Обратите внимание, что free(pointer) не устанавливает этот указатель в NULL.Если вы хотите, чтобы это было так, вы должны установить его самостоятельно, и это распространенная идиома в C:

free(pointer);
pointer = NULL;

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

2 голосов
/ 17 октября 2011

Единственная причина, по которой free() потерпит неудачу, заключается в том, что указатель, указанный вами, не обращается к выделенной куче.Это поведение четко определено: free() либо сработает, либо ваша программа остановится из-за нарушения прав доступа.

Хорошей практикой является повторная инициализация указателей после их освобождения именно для этой цели.Это позволяет вам:

  • Убедитесь, что вы не размещаете поверх уже выделенного указателя (таким образом теряете ссылку на исходные блоки и вызываете утечку) (несмотря на realloc ()).

  • Убедитесь, что вы не освобождаете недавно освобожденную память или память, которая никогда не была выделена

Обе функции упрощаются, проверяя,указатель инициализирован (или, NULL).

Лучше всего сделать это вручную и привыкнуть к этому.Я видел очень запутанных способов повторной реализации free(), чтобы автоматически инициализировать указатель, как этот маленький драгоценный камень, который также пытается избежать освобождения памяти, которая не была выделена:

void safe_free(void **p)
{                    
        if (*p != NULL) {
                free(*p);
                *p = NULL;
        }                 
}

Пожалуйста, не используйте этот код, он ужасно сломается на строгих платформах из-за разыменования указателя типа перфорированный.Кроме того, что, если указатель является строковым литералом?

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

2 голосов
/ 15 октября 2011

При бесплатном вызове указатель не устанавливается в NULL . Ты должен сделать это сам.

7.21:  Why isn't a pointer null after calling free()?
    How unsafe is it to use (assign, compare) a pointer value after
    it's been freed?

A:  When you call free(), the memory pointed to by the passed
    pointer is freed, but the value of the pointer in the caller
    probably remains unchanged, because C's pass-by-value semantics
    mean that called functions never permanently change the values
    of their arguments.  (See also question 4.8.)

    A pointer value which has been freed is, strictly speaking,
    invalid, and *any* use of it, even if it is not dereferenced,
    can theoretically lead to trouble, though as a quality of
    implementation issue, most implementations will probably not go
    out of their way to generate exceptions for innocuous uses of
    invalid pointers.

    References: ISO Sec. 7.10.3; Rationale Sec. 3.2.2.3.
1 голос
/ 15 октября 2011

Функция free принимает указатель на выделенную память, однако она не устанавливает этот указатель на NULL, на самом деле это невозможно, так как для этого потребуется адрес указателя.).

Типичный вариант использования в этом сценарии:

free(myptr);
myptr = NULL;
...