C-strdup()之后释放内存 [英] C - Freeing memory after strdup()

查看:430
本文介绍了C-strdup()之后释放内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从艰苦学习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).

BTW,如 Matt McNabb 所述,strdup是Posix中的标准配置,而不是C99语言规范.

BTW, as Matt McNabb commented, strdup is standard in Posix, not in the C99 language specification.

当然,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有时可能会调用有关内存碎片 的问题.

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()之后释放内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆