cstructsegmentation-faultfree

Usage of strdup()


Let's say we have a struct :

struct Person {
    char *name;
};

struct Person *Person_create(char *name){
  struct Person *who = malloc(sizeof(struct Person));
  assert(who != NULL);
  who->name = strdup(name);
  return who;
}

void Person_destroy(struct Person *who){
  assert(who != NULL);
  free(who->name);
  free(who);
}

And the main function :

int main(int argc,char *argv[]){

  struct Person *mike = Person_create("mike");
  Person_print(mike);
  Person_destroy(mike);

  return 0;
}

The above code won't work properly without the strdup() function. Valgrind says that the address you try to free with free(who->name) is not malloced. What's the story behind this, didn't I malloc that memory when I malloced the struct? And what difference does the strdup() make?


Solution

  • In your code each Person object involves two independent blocks of memory: the struct Person object itself and the separate memory block for the name. That separate memory block is pointed by the name pointer inside the struct. When you allocate struct Person by using malloc, you are not allocating any memory for the name. It is, again, an independent block of memory that should be allocated independently.

    How you are planning to allocate memory for the name is entirely up to you. If you use strdup (which is essentially a wrapper for malloc) as in your code above, then you will have to free it by free in the end.

    You did not explain what you mean by "without the strdup() function". What did you code look like without it? If you simply did

    who->name = name;
    

    then you made that who->name pointer to point directly to the string literal memory occupied by literal "mike". String literals reside in static memory. You are not allowed to free them. This is what valgrind is telling you.