我有一个函数,在调用时,从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
在我的程序终止时仍然可用,并且可以免费使用。为什么会泄漏记忆?
答案 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)