假设我们有一个结构:
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);
}
主要功能:
int main(int argc,char *argv[]){
struct Person *mike = Person_create("mike");
Person_print(mike);
Person_destroy(mike);
return 0;
}
如果没有
strdup()
函数,上面的代码将无法正常工作。 Valgrind 表示您尝试使用 free(who->name)
释放的地址并未被 malloc
ed。这背后的故事是什么,我在 malloc
编辑该结构时不是有 malloc
的记忆吗? strdup()
有什么区别?
在您的代码中,每个
Person
对象都涉及两个独立的内存块:struct Person
对象本身和名称的单独内存块。该单独的内存块由结构内部的 name
指针指向。当您使用 struct Person
分配 malloc
时,您没有为该名称分配任何内存。同样,它是一个独立的内存块,应该独立分配。
您计划如何为名称分配内存完全取决于您。如果您像上面的代码一样使用
strdup
(本质上是 malloc
的包装),那么您最终必须通过 free
释放它。
您没有解释“没有 strdup() 函数”的含义。如果没有它,你的代码会是什么样子?如果你只是这么做了
who->name = name;
然后您使
who->name
指针直接指向文字 "mike"
占用的字符串文字内存。字符串文字驻留在静态内存中。您不可以 free
他们。这就是 valgrind 告诉你的。
分配结构体会为指针 name 分配内存,但不会为 name 指向的指针分配任何内存。 那时 who->name 将是一些随机垃圾值,因此释放它没有任何意义。
strdup 在内部使用 malloc 为其复制的字符串分配内存。一旦你从 strdup 获得了一个返回的指针,你就可以而且应该在完成后释放它。
strdup没有调用malloc,只是字符串操作。您只 malloc 指向结构的指针,而不是内部成员