Bob
Bob

Reputation: 101

C struct memory management

Another C question:

let's say I have a struct that has a pointer member of char* type.

When I want to initialize an instance of the struct I call malloc:

MyStruct* ptr = (MyStruct*)malloc(sizeof(MyStruct)

And then allocate 256 bytes of memory for the char* member:

ptr->mem = (char*)malloc(sizeof(char)*256);

what happens to the pointer member and the memory it points to when I call free(ptr);? when I check the program with valgrind I see that I have a memory leak, but when I explicitly call free(ptr->member); I still have a memory leak and valgrind shows an "Invalid free" error

What's the proper way the manage the memory pointed by the member?

Upvotes: 1

Views: 1424

Answers (3)

Edmund
Edmund

Reputation: 10819

As soon as you call free(ptr), none of the members in ptr are valid any more. You can't do anything with them. But the memory that was pointed to be ptr->mem still needs to be freed. So you must either free(ptr->mem) first, or have otherwise copied that pointer somewhere so have a valid pointer to free.

The general pattern of allocating and freeing compound structures is something like (and it is helpful to wrap them up in nice clean functions that do this):

MyStruct* MakeMyStruct() {
    MyStruct* ptr = malloc(sizeof(MyStruct)); //N.B. don't need cast if it's C
    ptr->mem = malloc(sizeof(char)*256);
    //initialise other members
    return ptr;
}

void DestroyMyStruct(MyStruct *ptr) {
    //Free members first, then the struct
    free(ptr->mem);
    free(ptr);
}

If some of the members are complicated structs themselves, they would in turn be allocated/freed with MakeWhatever and DestroyWhatever instead of malloc and free in the above two functions.

Upvotes: 3

stefan bachert
stefan bachert

Reputation: 9608

You have to free ptr->member first, then the struct

free(ptr->member);
free(ptr);

Upvotes: 3

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272497

The rule of thumb is that you need one free for every (successful) call to malloc (and generally, these occur in the reverse order).

If you only free(ptr), then you have a memory leak (because there's no way to access the memory allocated for ptr->mem). If you only free(ptr->mem), then you haven't cleared up completely (not quite as bad as a memory leak).

Upvotes: 2

Related Questions