free()函数仅释放结构的第一个元素?

时间:2019-07-19 08:31:59

标签: c memory-leaks malloc free

我正在使用两种结构:

typedef struct ListNode{
    void* value;
    struct ListNode *next;
    struct ListNode *prev;
} Node;

typedef struct List{
    Node *first;
    Node *last;
    int count;
} List;

然后我声明这些变量并分配内存

List *x = calloc(1,sizeof(List));
Node *x1 = malloc(sizeof(Node));
Node *x2 = malloc(sizeof(Node));
x->first = x1;
x->last =x2;
x->count = 2;
free(x);

因此,我非常确定,如果我释放x,则x->countx->firstx->last也将消失。但是,在这种情况下,我使用gdb进行检查,令人惊讶的是,仅删除了x的第一个元素(例如:如果在结构List中,我将count放在顶部,那么它将仅删除count并保留保持原样)。为什么会发生这种情况?我如何free()整个结构?

3 个答案:

答案 0 :(得分:8)

您的假设是错误的。如果您执行free(x),则只释放包含x内容的内存块,但是由于该块包含指向其他块的指针,因此您需要{ {1}}首先。这是因为free()不在乎要释放的内存的内容,它不会做任何花哨的事情。如果您发现在使用free()之后修改了一些值,那是因为free()使用该内存来存储一些有用的内部值来跟踪内存使用情况,并且这只是巧合,如果“清除”结构中的指针。

free()结构的正确方法如下:

free()

这是一个视觉表示(请原谅我糟糕的笔迹):

enter image description here

答案 1 :(得分:1)

了解结构的内存布局很重要...我不是专家,所以这将真的得到简化:

列表x = [pointer-to-x1] [pointer-to-x2] [int](加上填充)

因此,当您运行calloc(1,sizeof(List))时,不会在与List相同的内存区域中创建x1和x2结构,因为它们只是指向内存中其他位置的指针。您只是为它们创建了一个小的参考,甚至还没有设置。因此,您必须分别分配x1和x2。

因此,当您释放(x)时,您也不会释放x1或x2。 free不知道如何,也不知道您为x1和x2运行了malloc。如果它尝试释放它,可能最终会过早释放内存或释放堆栈上的内存。它只会查看我上面绘制的内存区域。

在撰写本文时,看到另一个答案刚刚出现。Marco的回答很好!

答案 2 :(得分:1)

您似乎对电话free会发生什么期望无效。 您无法在GDB中验证free的结果。

释放内存位置并不意味着该位置的内存以任何方式被修改。它可能看起来仍然与以前相同。 OS或C运行时库可以将其设置为全零,但这不是强制性的。而且指针x不会改变。

释放地址仅意味着您告诉操作系统可以将其取回并提供给其他人。 调用free之后,您将不再被允许访问内存。 这就是free之后发生的一切。

因此,lastcount不会“消失”。

也就是说,您还存在其他人已经指出的内存泄漏问题。释放x不会释放通过x->firstx->last访问的任何其他内存。