为什么免费工作这样?

时间:2017-07-27 23:55:10

标签: c malloc ansi

给出以下代码:

typedef struct Tokens {
    char **data;
    size_t count;
} Tokens;

void freeTokens(Tokens *tokens) {
    int d;
    for(d = 0;d < tokens->count;d++)
        free(tokens->data[d]);
    free(tokens->data);
    free(tokens);
    tokens = NULL;
}

为什么我需要额外的费用:

free(tokens->data);

不应该在for循环中处理吗?

我已经对valgrind / drmemory进行了测试,并且顶部循环确实正确地释放了所有动态内存,但是如果我删除了已识别的行,则会泄漏内存。

Howcome?

3 个答案:

答案 0 :(得分:6)

让我们看一下您在该计划中使用的记忆图:

+---------+       +---------+---------+---------+-----+
| data    |  -->  | char *  | char *  | char *  | ... |
+---------+       +---------+---------+---------+-----+
| count   |            |         |         |
+---------+            v         v         v
                     +---+     +---+     +---+
                     | a |     | b |     | c |
                     +---+     +---+     +---+
                     |...|     |...|     |...|
                     +---+     +---+     +---+

在C中,我们可以为(更简单地说,一个数组)元素动态分配空间。但是,我们不能使用数组类型来引用该动态分配,而是使用指针类型。在这种情况下,指针只指向动态分配的数组的第一个元素。如果向指针添加1,则会获得指向动态分配数组的第二个元素的指针,添加两个指针以获取指向第二个元素的指针,依此类推。

在C中,括号语法(data[1])是添加和解除引用指针的简写。因此,C中的指针可以像数组一样使用。

在图中,data指向动态分配的数组中的第一个char *,该数组位于内存的其他位置。

data指向的数组的每个成员都是一个字符串,它本身是动态分配的(因为元素是char * s)。

因此,循环取消分配字符串('a...''b...''c...'等),free(tokens->data)释放数组data指向,最后,free(tokens)释放整个结构。

答案 1 :(得分:4)

data是指向指针的指针。这意味着data指向动态分配的指针数组,然后每个指针都指向实际数据。第一个for循环释放数组中的每个指针,但是你仍然需要将原始指针释放到已经释放的其他点的数组中。这就是你指出的那条线的原因。

答案 2 :(得分:3)

作为一般经验法则,每个malloc()都应该对free()进行相应的调用。如果你看看在这个程序中分配内存的代码,你很可能会看到与你在这里发布的代码非常严格的对应,从而释放内存。