我正在从学习硬汉在线课程中吸取教训。在下面的代码示例中,我不明白为什么需要进行两次free()
调用。我以为只需要调用free()
一次,因为只有一个malloc()
出现。有人可以澄清为什么我们需要两个吗?
如果我发表评论free(who->name);
,那么valgrind
告诉我,我已经失去了一大块内存,就像这样;
LEAK SUMMARY:
definitely lost: 21 bytes in 2 blocks
以下是代码:
#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;
}
答案 0 :(得分:15)
strdup(3) 记录为
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).
BTW,正如Matt McNabb所述,strdup
是Posix的标准,而不是C99语言规范。
当然free
只释放你传递它的内存区域(它不会神奇地和间接地释放你传递它的内存区域内指向的任何区域)。同样,free(3)说:
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 dynamic memory allocation。如果您不喜欢,请了解garbage collection。使用C on Linux和其他一些系统,您可以考虑使用Boehm's conservative garbage collector。然后,您将使用GC_MALLOC
和/或GC_MALLOC_ATOMIC
代替malloc
,GC_STRDUP
代替strdup
,您不必担心free
(如果需要,您有时可以使用GC_FREE
)。我发现它非常有用,但它确实有一些缺点(比malloc
慢一点,而且没有关于释放内存的明确保证......)。
了解memory corruption和memory leaks
顺便说一句,你应该先用所有警告和调试信息编译你的程序(例如gcc -Wall -g
)。然后,您可以使用调试器(gdb
),在达到malloc
后在main
设置断点,并查看何时调用malloc
。您会看到strdup
正在调用malloc
....
仅供参考,在Linux上,使用mmap(2)实现malloc
- 有时使用旧的sbrk(2) - 系统调用 - 来获取“大”内存区域(几千字节甚至兆字节),并且free
有时可能会调用munmap(2) - 对于这些大区域 - 但大多数情况下它只是将释放的块标记为可重用,因此可以在某些将来的调用中重用该块malloc
。因此,执行malloc
和free
的程序可能不会将以前使用的所有内存释放到内核中。另请参阅this question about memory fragmentation。