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 malloc
ed. What's the story behind this, didn't I malloc
that memory when I malloc
ed the struct? And what difference does the strdup()
make?
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.