C - strdup()后释放内存

And*_*y J 7 c memory

我正在从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)记录

   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).
Run Code Online (Sandbox Code Playgroud)

正如Matt McNabb评论的那样,BTW 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.
Run Code Online (Sandbox Code Playgroud)

阅读有关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可能不会将之前使用的所有内存释放到内核.另请参阅有关内存碎片的问题.