问题描述
我正在从艰苦学习C语言在线课程中学习.在下面的代码示例中,我不明白为什么需要两个free()
调用.我以为一个只需要调用free()
一次,因为只有一个malloc()
发生.有人可以弄清楚为什么我们需要两个吗?
I'm doing a lesson from the Learn C the Hard way online course. In the code sample below, I don't understand why the two free()
calls are necessary. I thought one would only need to call free()
once, because only one malloc()
occurs. Could somebody clarify why we need two?
如果我注释掉free(who->name);
,那么valgrind
告诉我,我丢失了一块"o内存",就像这样;
If I comment out free(who->name);
then valgrind
tells me that I've lost a chunk 'o memory, like so;
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;
}
推荐答案
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).
当然,free
仅释放您通过它的内存区域(它不会神奇地和间接地释放您通过它的内存区域内指向的任何区域).同样, free(3)说:
Of course free
only releases the memory zone that you pass it (it does not magically and indirectly free any zone pointed inside the memory zone you pass it). Again, free(3) says:
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动态内存分配.如果您不喜欢,请了解垃圾收集.在Linux和其他一些系统上的C语言中,您可以考虑使用 Boehm的保守垃圾收集器.然后,您将使用GC_MALLOC
和/或GC_MALLOC_ATOMIC
代替malloc
,并使用GC_STRDUP
代替strdup
,并且您将不必担心free
(如果需要,有时可以使用GC_FREE
) .我发现它非常有用,但是它确实有一些缺点(比malloc
慢一点,并且没有明确的释放内存的保证...).
Read much more about C dynamic memory allocation. If you don't like that, learn about garbage collection. With C on Linux and some other systems, you could consider using Boehm's conservative garbage collector. You'll then use GC_MALLOC
and/or GC_MALLOC_ATOMIC
instead of malloc
, and GC_STRDUP
instead of strdup
and you won't bother about free
(you might sometimes use GC_FREE
if wanted). I find it very useful, but it does have some drawbacks (a bit slower than malloc
, and no explicit guarantee about releasing memory...).
顺便说一句,您应该首先使用所有警告和调试信息来编译程序(例如gcc -Wall -g
).然后,您可以使用调试器(gdb
),在到达main
之后在malloc
中设置一个断点,并查看何时调用malloc
.您会看到strdup
正在调用malloc
....
BTW, you should first compile your program with all warnings and debug info (e.g. gcc -Wall -g
). Then you could use your debugger (gdb
), set a breakpoint in malloc
after main
has been reached, and see when malloc
is called. You'll see that strdup
is calling malloc
....
FYI,在Linux上,malloc
使用 mmap(2 )-有时是旧的 sbrk(2)-syscalls-获取大"内存区域(几千甚至几兆字节),free
有时可能会调用 munmap(2)-对于这些大区域-但大多数情况下,它只是将释放的块标记为可重用,因此该块可以在某些将来重用调用malloc
.因此,执行malloc
和free
的程序可能不会将以前使用的所有内存释放给内核.另请参见有关内存碎片 的问题.
FYI, on Linux, malloc
is implemented using mmap(2) -and sometimes the old sbrk(2)- syscalls -to get "large" memory regions (of several kilobytes or even megabytes), and free
may sometimes call munmap(2) -for these large regions- but most often it justs mark a freed block as reusable, so that block could be reused in some future calls to malloc
. Hence a program doing malloc
and free
might not release all it previously used memory to the kernel. See also this question about memory fragmentation.
这篇关于C-strdup()之后释放内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!