我正在从Learn C the Hard way在线课程中吸取教训.在下面的代码示例中,我不明白为什么这两个free()调用是必要的.我以为只需要拨打free()一次,因为只有一次malloc()发生.有人可以澄清我们为什么需要两个吗?
如果我发表评论free(who->name);然后valgrind告诉我,我已经失去了一大块记忆,就像这样;
LEAK SUMMARY:
definitely lost: 21 bytes in 2 blocks
Run Code Online (Sandbox Code Playgroud)
这是代码:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char *name;
int age;
int height;
int weight;
};
struct Person *Person_create(char *name, int age, int height, int weight)
{
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->name = strdup(name);
who->age = age;
who->height = height;
who->weight = weight;
return who;
}
void Person_destroy(struct Person *who)
{
assert(who != NULL);
free(who->name); /* Why this one??! */
free(who);
}
int main(int argc, char *argv[])
{
// make two people structures
struct Person *joe = Person_create(
"Joe Alex", 32, 64, 140);
struct Person *frank = Person_create(
"Frank Blank", 20, 72, 180);
// destroy them both so we clean up
Person_destroy(joe);
Person_destroy(frank);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Bas*_*tch 15
的strdup(3)被记录为
Run Code Online (Sandbox Code Playgroud)The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
正如Matt McNabb评论的那样,BTW strdup是Posix的标准,而不是C99语言规范.
当然free只释放你传递它的内存区域(它不会神奇地和间接地释放你传递它的内存区域内指向的任何区域).同样,free(3)说:
Run Code Online (Sandbox Code Playgroud)The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
阅读有关C动态内存分配的更多信息.如果您不喜欢,请了解垃圾收集.使用C on Linux和其他一些系统,您可以考虑使用Boehm的保守垃圾收集器.然后你将使用GC_MALLOC和/或GC_MALLOC_ATOMIC代替malloc,而GC_STRDUP不是strdup你不会打扰free(你可能有时会使用,GC_FREE如果需要).我发现它非常有用,但确实有一些缺点(比malloc释放内存要慢一些,并且没有明确的保证......).
顺便说一句,你应该首先用所有警告和调试信息编译你的程序(例如gcc -Wall -g).然后你可以使用你的调试器(gdb),在到达malloc之后设置断点main,并查看何时malloc被调用.你会看到这 strdup是在呼唤malloc....
在Linux上,仅供参考,malloc使用mmap(2) - 有时是旧的sbrk(2) - 系统调用 - 来获得"大"内存区域(几千字节甚至兆字节),free有时可能会调用munmap(2) -这些大区域 - 但大多数情况下它只是将一个释放的块标记为可重用,因此该块可以在以后的某些调用中重用malloc.因此,程序执行malloc并且free可能不会将之前使用的所有内存释放到内核.另请参阅有关内存碎片的问题.