【问题标题】:Confusing Valgrind output: indirectly lost blocks but no errors?令人困惑的 Valgrind 输出:间接丢失块但没有错误?
【发布时间】:2010-12-12 21:21:40
【问题描述】:

我正在运行 valgrind 3.5.0 来尝试消除程序中的内存泄漏。 我这样调用它:

valgrind --tool=memcheck --leak-check=yes --show-reachable=yes

在我的程序完成后,valgrind 报告说

==22926==
==22926== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 1)
==22926== malloc/free: in use at exit: 20,862 bytes in 425 blocks.
==22926== malloc/free: 25,361 allocs, 24,936 frees, 772,998 bytes allocated.
==22926== For counts of detected errors, rerun with: -v
==22926== searching for pointers to 425 not-freed blocks.
==22926== checked 91,884 bytes.

尽管告诉我有 0 个错误,但我担心分配和释放的数量不匹配。更多的 令人担忧的仍然是:

==22926== LEAK SUMMARY:
==22926==    definitely lost: 68 bytes in 1 blocks.
==22926==    indirectly lost: 20,794 bytes in 424 blocks.
==22926==      possibly lost: 0 bytes in 0 blocks.
==22926==    still reachable: 0 bytes in 0 blocks.
==22926==         suppressed: 0 bytes in 0 blocks.

还有额外的输出,与似乎是泄漏有关:

==22926== 20,862 (68 direct, 20,794 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 17
==22926==    at 0x40269EE: operator new(unsigned int) (vg_replace_malloc.c:224)
==22926==    by 0x807960B: OneTwoThree::OneTwoThree(Scenario const*) (onetwothree.cc:22)
==22926==    by 0x804DD69: main (scsolver.cpp:654)

在 OneTwoThree 的构造函数中,我有以下内容:

OneTwoThree::OneTwoThree (const Scenario* scenario) :
    Choice("123", scenario, new Solution (scenario->name(), scenario)),
    seen_(new bool [sol_->numVisits()])
{
}

稍后,在析构函数中,seen_ 被这样删除:

OneTwoThree::~OneTwoThree ()
{
    delete [] seen_;
}

没有与 seen_ 相关的内存重新分配;我只在过程中将布尔值翻转为真/假 运行我的程序。

我在这里看不到泄漏,我不明白 valgrind 试图告诉我什么。我一直在阅读 valgrind 手册(具体来说,this)但是 我开悟不多。

谁能帮我理解这个输出?

【问题讨论】:

  • 是否有可能Solution 对象本身 永远不会被销毁?
  • Choice 类是否取消分配它在构造函数中获得的指针?看起来更好的设计是在同一个类中拥有指针所有权 - 如果 OneTwoThree 分配内存,同一个实例应该取消分配它。
  • Choice 构造函数及其亲属是否完全释放所有内容?

标签: c++ memory-leaks valgrind


【解决方案1】:

对 OP 的评论很准确;在构造函数中创建的解决方案对象从未被删除。我已经修复了令人震惊的疏忽,并摆脱了在负责它们的对象的构造函数之外创建新对象的丑陋代码。

感谢 Artelius、Nikolai 和 Jonathan!

【讨论】:

  • 此外,在持有资源时,内存泄漏可能会在赋值运算符中蔓延。遵循三巨头法则:每当您编写 Copy Constructor、Assignment Operator 或 Destructor 之一时;另外两个也写。就个人而言,我认为赋值运算符最好用复制和交换习语来编写。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-23
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 2013-07-20
  • 1970-01-01
相关资源
最近更新 更多