开发者

Memory leak in C++ seems to get worse after adding delete statements

Edit: Can someone explain why adding the delete operators do not change the Valgrind output? Please do not ask me to read C++ books, I have browsed through a couple and have not found the answers there.

I am new to C++, having come from the java world, I seem to have trouble understanding how to use new and delete operators.

I have a method (myMethod()) which initiates a class, MyClass. In MyClass there are a few arrays and few other objects being created using the new and new[] operators. Initially I did not have a destructor written for this class (I assumed that when the control returns to main from my method, these the MyClass object and everything related to it would be automatically "freed").

When I ran my program with Valgrind, this is the leak summary I got:

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

So I added a destructor which deletes all the arrays and sets the objects to null. I do not explicitly call delete on the MyClass object. Now when I run my program using Valgrind, this is the leak summary I get.

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-reac开发者_开发知识库hable=yes

When I explicitly delete the MyClass object, the nubmer of bytes lost is more!

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

I tried renaming the destructor to a method freeMemory() and then called freeMemory() before exitting from myMethod() and this is the leak summary. This is higher than either of them.

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

I guess my question is what is going on? Valgrind seems to indicate that the leak is in the constructor for MyClass and in a method in MyClass. Can someone explain to me how the new and delete operators work? I am not able to find a clear resource online, so if anyone can point me to such resource, that would be great too!


Since you're coming from Java, I should mention first that most often you do not need to use new in C++.

If you need a variable of type T, then just declare a variable of type T. That's it.

For your array, instead of using a pointer and new, use a std::vector, like

#include <vector>

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

It manages the memory automatically and correctly.

As to the error you are encountering, it is probably due to failure to consider all ways that your object can be copied. There is a rule of 3 (for C++98) that says that if you need any of custom destructor, custom copy constructor, or custom copy assignment operator, then you probably need all three. But again, instead of fiddling with that, which is difficult to get right, just use std::vector, or some other container.

And where you do need to manage lifetimes more directly, use smart pointers such as std::auto_ptr (from the standard library) and boost::shared_ptr (from the Boost library). That centralizes the tricky lifetime management code. Out of sight, Just Working™.

Cheers & hth.


Without seeing the code it is not possible to tell you exactly what to do to fix your leaks.

Note, though, that when you added destructors you reduced the amount of memory leaked it's just that much of that memory has moved from "indirectly lost" to "definitely lost" which means that your destructors are not cleaning up everything.

In most application code, though, you should rarely have to use new and almost never new[], delete or delete[]. Typically containers (such as std::vector) and smart pointers (such as shared_ptr) can be used to remove all error prone manual memory management from an application.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜