为什么会泄漏内存?

时间:2011-08-11 16:10:21

标签: c memory memory-leaks valgrind

我有一个函数,在调用时,从struct Pieces*获取struct Torrent字段,并根据char数组中包含的信息对其进行初始化。

这是函数调用的样子(metadata.c:230):

get_pieces(t.pieces, &t.num_pieces, data);

get_pieces()函数中,我初始化t.pieces,就像这样(metadata.c:65):

pieces = calloc(*num_pieces, sizeof(struct Piece));

然而,当我运行valgrind时,它说:

==8701== 76,776 bytes in 1 blocks are definitely lost in loss record 634 of 634
==8701==    at 0x4C28349: calloc (vg_replace_malloc.c:467)
==8701==    by 0x4025A4: get_pieces (metadata.c:65)
==8701==    by 0x402CDB: init_torrent (metadata.c:230)
==8701==    by 0x404018: start_torrent (torrent.c:35)
==8701==    by 0x40232E: main (main.c:17)

即使指针t->pieces在我的程序终止时仍然可用,并且可以免费使用。为什么会泄漏记忆?

完整源代码位于https://github.com/robertseaton/slug

3 个答案:

答案 0 :(得分:8)

你有

void get_pieces (struct Piece* pieces, uint64_t* num_pieces, char* data)
{
    /* ... */
    pieces = malloc(sizeof(struct Piece) * *num_pieces);
}

函数完成后,调用者作为第一个参数传递的对象不变,因此 malloc的结果将丢失。因此,我看不出你如何释放pieces

修改

用户user786653在评论中观察到,您需要更改您的功能:

void get_pieces(struct Piece **pieces...)
{
    /* ... */
    *pieces = malloc(sizeof(struct Piece) * num_pieces);
}

答案 1 :(得分:4)

这会泄漏内存,因为您的get_pieces函数正在传递一个指向Pieces:

的指针
void get_pieces (struct Piece* pieces, ...

然后将内存分配给此方法内的pieces。当它返回时,任何东西都不再可以访问分配的内存。

这是因为你的指针是按值传递的 - 重新分配指针并不会改变调用函数的副本。为了影响该调用函数,您必须将指针传递给指针,以便正确分配原始副本:

void get_pieces (struct Piece** pieces, ...
     // ...
      *pieces = malloc(...

并且,在呼叫站点,将地址传递给指针。

答案 2 :(得分:0)

在通话中

get_pieces(t.pieces, &t.num_pieces, data)

您正在通过值传递指针t.pieces,因此将其复制以在函数中使用。由于您在函数内部但不在外部分配它,并且这些现在是两个不同的指针,因此永远不会分配外部指针。函数内部的指针通过堆栈展开被破坏,分配的内存位于堆上,被遗忘。

您可以通过更改对

的调用来解决此问题
get_pieces(&t.pieces, &t.num_pieces, data)