添加删除语句后,C++中的内存泄漏似乎变得更糟

Anu*_*Anu 0 c++ valgrind memory-leaks delete-operator

编辑:有人可以解释为什么添加删除操作符不会更改Valgrind输出?请不要让我阅读C++书籍,我浏览了一对夫妇并且没有在那里找到答案.

我是C++的新手,来自java世界,我似乎无法理解如何使用new和delete运算符.

我有一个方法(myMethod())启动一个类,MyClass.在MyClass中,使用new和new []运算符创建了一些数组和很少的其他对象.最初我没有为这个类编写析构函数(我假设当控件从我的方法返回到main时,这些MyClass对象以及与它相关的所有内容都会自动"释放").

当我用Valgrind运行我的程序时,这是我得到的泄漏摘要:

==9446== LEAK SUMMARY:
==9446==    definitely lost: 1,957,019 bytes in 38 blocks.
==9446==    indirectly lost: 4,171,184 bytes in 3,040 blocks.
==9446==      possibly lost: 0 bytes in 0 blocks.
==9446==    still reachable: 91,984 bytes in 991 blocks.
==9446==         suppressed: 0 bytes in 0 blocks.
==9446== Reachable blocks (those to which a pointer was found) are not shown.
==9446== To see them, rerun with: --show-reachable=yes
Run Code Online (Sandbox Code Playgroud)

所以我添加了一个析构函数,它删除所有数组并将对象设置为null.我没有在MyClass对象上显式调用delete.现在,当我使用Valgrind运行我的程序时,这是我得到的泄漏摘要.

LEAK SUMMARY:
==9223==    definitely lost: 1,957,019 bytes in 38 blocks.
==9223==    indirectly lost: 4,171,184 bytes in 3,040 blocks.
==9223==      possibly lost: 0 bytes in 0 blocks.
==9223==    still reachable: 91,984 bytes in 991 blocks.
==9223==         suppressed: 0 bytes in 0 blocks.
==9223== Reachable blocks (those to which a pointer was found) are not shown.
==9223== To see them, rerun with: --show-reachable=yes
Run Code Online (Sandbox Code Playgroud)

当我明确删除MyClass对象时,丢失的字节数更多!

==9268== LEAK SUMMARY:
==9268==    definitely lost: 3,353,187 bytes in 1,253 blocks.
==9268==    indirectly lost: 28,376 bytes in 343 blocks.
==9268==      possibly lost: 0 bytes in 0 blocks.
==9268==    still reachable: 91,984 bytes in 991 blocks.
==9268==         suppressed: 0 bytes in 0 blocks.
==9268== Reachable blocks (those to which a pointer was found) are not shown.
==9268== To see them, rerun with: --show-reachable=yes
Run Code Online (Sandbox Code Playgroud)

我尝试将析构函数重命名为方法freeMemory(),然后在从myMethod()退出之前调用freeMemory(),这就是泄漏摘要.这比其中任何一个都要高.

== LEAK SUMMARY:
==8998==    definitely lost: 5,271,299 bytes in 1,205 blocks.
==8998==    indirectly lost: 67,264 bytes in 410 blocks.
==8998==      possibly lost: 0 bytes in 0 blocks.
==8998==    still reachable: 91,984 bytes in 991 blocks.
==8998==         suppressed: 0 bytes in 0 blocks.
==8998== Reachable blocks (those to which a pointer was found) are not shown.
==8998== To see them, rerun with: --show-reachable=yes
Run Code Online (Sandbox Code Playgroud)

我猜我的问题是怎么回事?Valgrind似乎表明泄漏是在MyClass的构造函数和MyClass中的方法中.有人可以向我解释新的和删除操作符的工作原理吗?我无法在网上找到明确的资源,所以如果有人能指出我这样的资源,这也会很棒!

Che*_*Alf 6

既然你来自Java,我首先要提到的是,你通常不需要new在C++中使用它.

如果你需要一个类型的变量T,那么只需声明一个类型的变量T.而已.

对于你的数组,而不是使用指针,并new使用std::vector,像

#include <vector>

int main()
{
    std::vector<int>  v( 10 );    // 10 elements
    v.resize( 42 );               // now 42 elements
}
Run Code Online (Sandbox Code Playgroud)

它自动正确地管理内存.

至于您遇到的错误,可能是由于未能考虑您的对象可以复制的所有方式.有一个规则3(对于C++ 98),如果你需要任何自定义析构函数,自定义复制构造函数或自定义复制赋值运算符,那么你可能需要这三个.但是,再次,而不是摆弄难以正确的,只是使用std::vector,或其他一些容器.

如果您需要更直接地管理生命周期,请使用智能指针,例如std::auto_ptr(来自标准库)和boost::shared_ptr(来自Boost库).这集中了棘手的生命周期管理代码.看不见,Just Working™.

干杯和hth.

  • @sarnold:我写了很多没有`new`的代码,没有`delete`或内存泄漏的完整项目.如果你只在需要时使用`new`,而在所有其他情况下使用*smart pointers* - 避免使用原始指针代码将更健壮,更易于维护. (3认同)
  • 这实际上取决于您希望变量存在的位置 - 如果它只应该存在于方法的生命周期中,那么您的建议非常好.但对于仅在特定调用链中不存在的变量(假设您希望存储指向从调用链返回的结构或对象中的对象的指针),使用`new`在堆上分配对象是最佳选择,并假装"新"总是一个糟糕的选择是一种伤害.仍然,+1推荐一种机制,减少"新"与"删除"不匹配的机会. (2认同)