1

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.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Tasha R
  • 33
  • 1
  • 7

1 Answers1

6

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..

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 2
    You also would not `free` the `name` member *in this example*, because it is a pointer to a string literal – Weather Vane Nov 01 '16 at 17:36
  • @WeatherVane Sir, tried to clarify a bit, is that worthy? – Sourav Ghosh Nov 01 '16 at 17:43
  • Yes, I already gave UV. On from my other comment I was thinking about the case where memory for a name came from `malloc` and that pointer was similarly copied to another `struct`: there could be a danger that this pointer was later freed *twice*, when there was only one allocation. – Weather Vane Nov 01 '16 at 17:49
  • Sorry, I'm new to using structures and malloc. In my code I'm only using free(employee_1) which is the pointer returned by malloc. So when I use malloc for my struct, is the pointer that it returns only used for the first item in my struct? When deallocating the pointer returned by malloc it only removes the name from memory so I'm assuming I've misunderstood the function. – Tasha R Nov 01 '16 at 17:49
  • It is for the whole struct that you allocated originally: but although the pointer then becomes invalid it *might* still point to the data, until such time as the freed memory was used for another process. So it might look as though it still exists - but using it is undefined behaviour. – Weather Vane Nov 01 '16 at 17:51
  • @Tasha_8608 nopes, I think I got your problem. You're trying to access the pointer _after_ you've called `free()` to check the values, right? There lies the problem. Don;t do that, that's UB. Just stick to `free(employee_1)` and be rest assured that all the memory will be freed. – Sourav Ghosh Nov 01 '16 at 17:51