mariekart42
mariekart42

Reputation: 51

free pointer passed to another function in C

I want to free a pointer in another function to save lines in my actual function, but when i use this self-written function:

void free_func(char *ptr1, char *ptr2)
{
    if (ptr1)
    {
        free(ptr1);
        ptr1 = NULL;
    }
    if (ptr2)
    {
        free(ptr2);
        ptr2 = NULL;
    }
}

it doesn't free my pointer. This is my main function where i call my free_function:

int main(void)
{
    char    *test;

    test = (char *)calloc(5, sizeof(char));
    test[0] = 'h';
    test[1] = 'e';
    test[2] = 'y';
    test[3] = '\0';

    printf("test before: %s\n", test);
    //free_func(test, 0, 0);
    free(test);
    test = NULL;
    printf("test after: %s\n", test);

    return(0);
}

This will give me the expected output:

test before: hey
test after: (null)

But if i comment the line where i free and use NULL, and uncomment my free_func, i will get this output:

test before: hey
test after: hey

My question now: why does my self written free function does something different, then the actual same lines in my main function?

Upvotes: 2

Views: 529

Answers (1)

ikegami
ikegami

Reputation: 386631

it doesn't free my pointer.

You are mistaken. It does free the memory to which your pointer points (i.e. the memory returned be calloc).

There's no way to check this. Well, short of using something like -fsanitize=address or valgrind to check for memory leaks.

why does my self written free function does something different, then the actual same lines in my main function?

Actually, they do exactly the same thing. They free the memory, then set the variable to NULL.

The only difference is that the variable you print (test) isn't the variable you set to NULL (ptr1) when using the function. If you want the function to change the variable in the caller, you will need to give it the address the variable.

void free_and_set_null( void **pp ) {
    free( *pp );
    *pp = NULL;
}

int main( void ) {
   char *p = malloc( 1 );

   // ...

   free_and_set_null( &p );
}

At least, that's the normal solution. It doesn't quite work here since we want to accept any kind of pointer. On a x86/x86-64, all pointers are the same size, and NULL is the same for every type of pointer. But that's not the case everywhere. As such, the above code violates the standard and warns.

Here, a macro could be used.

#ifdef _DEBUG
#define SAFE_FREE( p ) do{ free( p ); p = NULL; } while 0
#else
#define SAFE_FREE( p ) free( p )
#endif

int main( void ) {
   char *p = malloc( 1 );

   // ...

   SAFE_FREE( p );
}

Upvotes: 6

Related Questions