为什么会泄漏内存?

发布于 2024-11-29 06:24:17 字数 951 浏览 0 评论 0原文

我有一个函数,当调用时,它从 struct Torrent 中获取 struct Pieces* 字段,并根据 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 获取。

I have a function that, when called, takes a struct Pieces* field from a struct Torrent and initializes it according to the information contained in a char array.

Here is what the function call looks like (metadata.c:230):

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

In the get_pieces() function, I initialize t.pieces, like so (metadata.c:65):

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

However, when I run valgrind, it says:

==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)

even though a pointer, t->pieces, is still available when my program terminates and can be free'd. Why does this leak memory?

The full source code is available at https://github.com/robertseaton/slug.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

牵强ㄟ 2024-12-06 06:24:17

函数完成后,调用者

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

作为第一个参数传递的对象没有改变,因此ma​​lloc的结果丢失了。因此我不知道如何释放碎片

编辑

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

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

You have

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

After the function is done, the object passed by the caller as the first argument is unchanged, so the result of malloc is lost. Therefore I don't see how you can free pieces.

EDIT

As user user786653 observes in the comments, you need to change your function:

void get_pieces(struct Piece **pieces...)
{
    /* ... */
    *pieces = malloc(sizeof(struct Piece) * num_pieces);
}
演多会厌 2024-12-06 06:24:17

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

void get_pieces (struct Piece* pieces, ...

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

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

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

并且,在调用站点,将地址传递给指针。

This leaks memory because your get_pieces function is passing in a pointer to Pieces:

void get_pieces (struct Piece* pieces, ...

You then allocate memory to pieces inside of this method. When it returns, that allocated memory is no longer accessible by anything.

This is because your pointer is passed by value - reassigning the pointer does not change the calling function's copy. In order to affect that calling function, you'd have to pass a pointer to the pointer, so you can assign the original copy correctly:

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

And, at the call site, pass in the address to the pointer.

东风软 2024-12-06 06:24:17

在调用中,

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

您按值传递指针 t.pieces,因此它会被复制以在函数中使用。由于您在函数内部而不是外部对其进行赋值,并且现在它们是两个不同的指针,因此外部指针永远不会被赋值。函数内部的指针通过堆栈展开被销毁,分配的内存位于堆上,被遗忘。

您可以通过将调用更改为来解决此问题

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

In the call

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

you are passing the pointer t.pieces by value, so it is copied for use in the function. Since you assign to it inside the function but not outside, and these are now two different pointers, the outer pointer is never assigned. The pointer inside the function is destroyed via stack unwinding and the allocated memory sits there on the heap, forgotten.

You can fix this by changing the call to

get_pieces(&t.pieces, &t.num_pieces, data)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文