[c] C - freeing structs

Let's say I have this struct

typedef struct person{
    char firstName[100], surName[51]
} PERSON;

and I am allocating space by malloc and filling it with some values

PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");

What is the correct and safe way to free all memory taken by that struct? Is "free(testPerson);" enough or do I need to free each struct's attribute one by one?

It leads me to another question - how are structures stored in memory? I noticed a strange behaviour - when I try to print structure address it's equal to it's first attribute's address.

printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);

Which means that this free(testPerson) should be equal to this free(testPerson->firstName);

and that's not what I want to do.

Thanks

This question is related to c struct malloc

The answer is


You can't free types that aren't dynamically allocated. Although arrays are syntactically similar (int* x = malloc(sizeof(int) * 4) can be used in the same way that int x[4] is), calling free(firstName) would likely cause an error for the latter.

For example, take this code:

int x;
free(&x);

free() is a function which takes in a pointer. &x is a pointer. This code may compile, even though it simply won't work.

If we pretend that all memory is allocated in the same way, x is "allocated" at the definition, "freed" at the second line, and then "freed" again after the end of the scope. You can't free the same resource twice; it'll give you an error.

This isn't even mentioning the fact that for certain reasons, you may be unable to free the memory at x without closing the program.

tl;dr: Just free the struct and you'll be fine. Don't call free on arrays; only call it on dynamically allocated memory.


First you should know, how much memory is allocated when you define and allocate memory in below case.

   typedef struct person{
       char firstName[100], surName[51]
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

1) The sizeof(PERSON) now returns 151 bytes (Doesn't include padding)

2) The memory of 151 bytes is allocated in heap.

3) To free, call free(testPerson).

but If you declare your structure as

  typedef struct person{
      char *firstName, *surName;
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

then

1) The sizeof(PERSON) now returns 8 bytes (Doesn't include padding)

2) Need to allocate memory for firstName and surName by calling malloc() or calloc(). like

        testPerson->firstName = (char *)malloc(100);

3) To free, first free the members in the struct than free the struct. i.e, free(testPerson->firstName); free(testPerson->surName); free(testPerson);


free is not enough, free just marks the memory as unused, the struct data will be there until overwriting. For safety, set the pointer to NULL after free.

Ex:

if (testPerson) {
    free(testPerson);
    testPerson = NULL;
}

struct is similar like an array, it is a block of memory. You can access to struct member via its offset. The first struct's member is placed at offset 0 so the address of first struct's member is same as the address of struct.


This way you only need to free the structure because the fields are arrays with static sizes which will be allocated as part of the structure. This is also the reason that the addresses you see match: the array is the first thing in that structure. If you declared the fields as char * you would have to manually malloc and free them as well.


Mallocs and frees need to be paired up.

malloc grabbed a chunk of memory big enough for Person.

When you free you tell malloc the piece of memory starting "here" is no longer needed, it knows how much it allocated and frees it.

Whether you call

 free(testPerson) 

or

 free(testPerson->firstName)

all that free() actually receives is an address, the same address, it can't tell which you called. Your code is much clearer if you use free(testPerson) though - it clearly matches up the with malloc.


Because you defined the struct as consisting of char arrays, the two strings are the structure and freeing the struct is sufficient, nor is there a way to free the struct but keep the arrays. For that case you would want to do something like struct { char *firstName, *lastName; }, but then you need to allocate memory for the names separately and handle the question of when to free that memory.

Aside: Is there a reason you want to keep the names after the struct has been freed?


Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to struct

How to search for an element in a golang slice "error: assignment to expression with array type error" when I assign a struct field (C) How to set default values in Go structs How to check for an empty struct? error: expected primary-expression before ')' token (C) Init array of structs in Go How to print struct variables in console? Why Choose Struct Over Class? How to return a struct from a function in C++? Initializing array of structures

Examples related to malloc

Initializing C dynamic arrays C - freeing structs malloc an array of struct pointers How do I free memory in C? How to dynamically allocate memory space for a string and get that string from user? Incompatible implicit declaration of built-in function ‘malloc’ Dynamically create an array of strings with malloc How is malloc() implemented internally? Why do I get a C malloc assertion failure? What is a Memory Heap?