【问题标题】:Why does this Deque destructor have memory leak为什么这个 Deque 析构函数有内存泄漏
【发布时间】:2018-08-19 10:42:46
【问题描述】:

我使用双向链表在 C++ 中实现 Deque。

析构函数:

Deque::~Deque() 
{
    while (this->left_p) 
    {
        node *temp = this->left_p;
        this->left_p = this->left_p->next;
        delete temp;
    }

    this->right_p = NULL;
}

当我使用valgrind --leak-check=full ./a.out 来检查内存泄漏只是为了测试我的析构函数时,我得到了以下输出:

==2636== 
==2636== HEAP SUMMARY:
==2636==     in use at exit: 72,704 bytes in 1 blocks
==2636==   total heap usage: 1,003 allocs, 1,002 frees, 97,760 bytes allocated
==2636== 
==2636== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==2636==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2636==    by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==2636==    by 0x40106B9: call_init.part.0 (dl-init.c:72)
==2636==    by 0x40107CA: call_init (dl-init.c:30)
==2636==    by 0x40107CA: _dl_init (dl-init.c:120)
==2636==    by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
==2636== 
==2636== LEAK SUMMARY:
==2636==    definitely lost: 0 bytes in 0 blocks
==2636==    indirectly lost: 0 bytes in 0 blocks
==2636==      possibly lost: 0 bytes in 0 blocks
==2636==    still reachable: 72,704 bytes in 1 blocks
==2636==         suppressed: 0 bytes in 0 blocks
==2636== 
==2636== For counts of detected and suppressed errors, rerun with: -v
==2636== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

我不明白为什么 1003 个分配器中仍有一个不是空闲的。

为什么我有一个内存泄漏?我的析构函数有什么问题?

在这里测试代码:

/* Deque Test Program 6 */
#include <cstring>
#include <iostream>
#include "Deque.h"

using namespace std ;

int main (int argc, char * const argv[]) {
    cout << "\n\nDeque Class Test Program 6 - START\n\n";

    // Make a Deque
    Deque * dq1 = new Deque();
    for( int i = 0 ; i<1 ; i++ ){
        dq1->push_left(1);
        // dq1->display();
    }
    cout << "Size=" << dq1->size() << endl ;

    // The destructor should delete all the nodes.
    delete dq1 ;

    cout << "\n\nDeque Class Test Program 6 - DONE\n\n";
    return 0;
}

编辑:删除实现代码。

【问题讨论】:

  • 请提取一个 MCVE 并将其放入您的问题中。外部链接太不稳定,而且往往会发生变化。
  • 如果没有 Deque.cpp 的知识,就无法判断这里出了什么问题。
  • @Rudi 对不起。更新了我的问题
  • 我无法重现该错误。要么你在本地修改了一些东西,要么你在 C 标准库中遇到了一个错误。当您使用 valgrind 时,您还应该使用 -g 开关编译和链接所有程序,因为 valgrind 在可以找到调试信息时会提供更好的输出。 (作为旁注,我还建议在将 .cpp 转换为 .o 时删除显式的 g++ -c 调用,因为 make 有一个针对这种情况的内置规则。)
  • 删除左侧的所有节点后,继续设置this-&gt;right_p = NULL;。在我看来不是很谨慎。

标签: c++ algorithm valgrind deque


【解决方案1】:

本质上,这不是你的代码的错,而是 valgrind 的错。

检查另一个有同样问题的问题: Valgrind: Memory still reachable with trivial program using <iostream>

引自帖子:

首先:放松,这可能不是一个错误,而是一个特性。 C++ 标准库的许多实现都使用它们自己的内存池分配器。许多被破坏对象的内存不会立即释放并返回给操作系统,而是保留在池中以供以后重用。程序退出时未释放池的事实导致 Valgrind 报告此内存仍可访问。但是,在出口处不释放池的行为可以称为库的错误。

希望有帮助:)

【讨论】:

    【解决方案2】:

    valgrind 报告的内存泄漏似乎不在您的代码中:

    ==2636== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
    ==2636==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==2636==    by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
    ==2636==    by 0x40106B9: call_init.part.0 (dl-init.c:72)
    ==2636==    by 0x40107CA: call_init (dl-init.c:30)
    ==2636==    by 0x40107CA: _dl_init (dl-init.c:120)
    

    这似乎是全局对象的构造函数中的堆分配。 (理论上,如果 operator new 被作为尾调用调用,它仍然可能来自您的代码,因此它不会出现在回溯中,但我在您的 cdoe 中没有看到这样的对象声明。)

    这也不是真正的泄漏,它只是程序启动时在堆上分配的一些数据。如果您为libstdc++ 安装调试信息,那么您可能会得到实际分配的提示。然后您还可以在call_init 上设置断点并逐步执行早期进程初始化,以查看被调用的构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      相关资源
      最近更新 更多