Gray-Vine42 Gray-Vine42 - 1 month ago 11
C Question

C - How to use free() to free a struct in memory?

I need some help to deallocate memory for a struct.

I'm storing a pointer to a memory location in a variable but I want to deallocate the memory after use. However, when I try to deallocate the memory it only deallocates the first structure item (

name
) and
age
remains in memory. My code can be seen below.

int main(int argc, char **argv)
{
struct employee {
char *name;
int age;
};

// Make pointer, employee struct and put struct in memory at pointer location
struct employee *employee_1;
struct employee new_employee;
new_employee.name = "Sue";
new_employee.age = 26;
employee_1 = (struct employee *) malloc(sizeof(new_employee));
(*employee_1).name = new_employee.name;
(*employee_1).age = new_employee.age;

// ... Some operations done
// Deallocate memory location
free(employee_1);
return 0;
}


Both the name and age of the employee are definitely being stored at the memory location, but I can't deallocate them both. I have tested this to have more than two items in the struct and each time it's only the first item that is deallocated.

I have tried a few different methods like deallocating each individually in case that would work
free((*employee_1).name)
but this throws an error. Any help would be appreciated.

Answer

No, you don't deallocate age yourself. That is not a "pointer returned by malloc() and family", so you don't need to (call) free() on that.

Quoting C11, chapter ยง7.22.3.3, (emphasis mine)

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Also, FWIW, free() takes a pointer, so even passing the address of age member variable will also be wrong. The allocated memory will be automatically deallocated by the OS or memory manager, once the program terminates.

To sum up, you should only call free() with pointers returned by memory management functions (i.e, malloc() and family), that's it. Other pointers, even if they are pointers, if not allocated memory via memory management functions, (i.e, does snot store a pointer returned by malloc() and family) need not to be free()-d.

For example, in your case, you do not call free() on (*employee_1).name (rather , use employee_1->name, gives better readability, IMHO), as the pointer is not returned by memory management functions. Doing so will invoke undefined behavior.

That said, please see this discussion on why not to cast the return value of malloc() and family in C..

Comments