Function free() in C isn't working for me

2019-01-26 02:46发布

问题:

I have been trying to free memory allocated via malloc() using free().

Some of the structs it does free but leaves some the way they were and they also remain linked to their children. It also never frees the root (gRootPtr) for a binary tree.

I am using Xcode to find out if the memory used by the binary tree has been freed and also use the if statement.

Code I am using to free the memory:

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

Code I am using to see if the memory has been freed.

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

回答1:

First, free does not change the pointer itself.

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

If you want the pointer to go back to NULL, you must do this yourself.

Second, there are no guarentees about what will happen to the memory pointed to by the pointer after the free:

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!

Note that this means that you cannot actually test if free() works. Strictly speaking, it's legal for free() to be implemented by doing absolutely nothing (although you'll run out of memory eventually if this is the case, of course).



回答2:

That check won't check if the variable is freed. Note that free(pointer) does not set that pointer to NULL. If you want that to be the case, you have to set it yourself, and it is a common idiom in C:

free(pointer);
pointer = NULL;

to signal that you already freed that pointer.



回答3:

Calling free does not set the pointer to NULL. You have to do that yourself.

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.


回答4:

The only reason free() would fail is if the pointer you give it does not dereference to allocated heap. This behavior is clearly defined, free() will either work, or your program will halt due to an access violation.

It is good practice to re-initialize your pointers after freeing them, for just this purpose. This lets you:

  • Make sure you don't allocate on top of an already allocated pointer (thus losing the reference to the original blocks and causing a leak) (realloc() notwithstanding).

  • Make sure you don't free recently freed memory, or memory that was never allocated

Both become easy by testing to see if the pointer is initialized (or, NULL).

It's best to just do this manually and get in the habit of doing so. I have seen some very convoluted ways of re-implementing free() so that re-initializes the pointer automatically, like this little gem that also attempts avoid freeing memory that wasn't allocated:

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

Please, don't use that code, it will break horribly on strict platforms due to dereferencing a type punned pointer. Additionally, what if the pointer is a string literal?

Instead, just make sure you keep track of your pointers and initialize them after freeing.



回答5:

The function free takes a pointer to allocated memory, it does not however set that pointer to NULL, in fact there is no way it could do so (it would need to take the address of a pointer for that).

Typical use case in this scenario is:

free(myptr);
myptr = NULL;


标签: c malloc free std