【问题标题】:Why does this leak memory?为什么会泄漏内存?
【发布时间】:2011-10-25 03:31:57
【问题描述】:

我有一个函数,当被调用时,它会从 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获得。

【问题讨论】:

  • 在哪里以及如何释放分配的内存?
  • 他没有释放它,但仍然有对它的引用(或者至少他认为有对它的引用......)

标签: c memory memory-leaks valgrind


【解决方案1】:

你有

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

函数完成后,调用者作为第一个参数传递的对象没有改变,所以malloc的结果丢失了。因此,我不知道您如何释放pieces

编辑

正如用户 user786653 在 cmets 中观察到的,您需要更改函数:

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

【讨论】:

  • +1 我正在用同样的东西写一个答案。 OP 应该将其更改为 struct Piece** pieces*pieces = malloc(....
  • @user786653 我认为这是 OP 应该做的。
【解决方案2】:

通话中

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

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

您可以通过将调用更改为

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

【讨论】:

    【解决方案3】:

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

    void get_pieces (struct Piece* pieces, ...
    

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

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

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

    然后,在调用站点,将地址传递给指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 2013-07-12
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多