Re: stl::string memory leak associated with polymorphism
Hi,
Thanks a lot! I did not know about this fact; however I should have
known.
I now just added
virtual ~Base() {}
and everything works fine. I would never have found out this on my own
:)
So if I understood it correctly, each class has a default-destructor
(which is NOT virtual) which deals with the clean-up of all member
variables. When using polymorphism, only the default destructor of Base
is called (because only the pointer to this type is available). By
making the default-destructor of Base virtual, polymorphim comes into
play and the destructor of Final is called instead (which in turn will
continue with the Base destructor). That's a beautiful concept - as
soon as one knows about it :))
(For others, here ist a link which explains the merits of the virtual
destructor: http://www.codersource.net/cpp_virtual_destructors.html)
Best,
Daniel
David Wilkinson wrote:
daniel@fin.de wrote:
Hi,
I spent a week on tracking down some memory leak which apparently comes
from the stl or the c++-Implementation itself. I tried Visual Studio
2002 and Visual C++ 2005 which both created the problem. Since I do not
have anything sophisticated as for example Bounds Checker, I used the
debug heap. Here is the code, (compile an run in debug mode in a
default "Windows Console Application" project):
-----------------------------------------------------------------------
-----------------------------------------------------------------------
#include <crtdbg.h>
#include <string>
using namespace std;
class Base
{
public:
virtual void test() =0;
};
class Final : public Base
{
public:
string str;
void test() { str ="0123456789012345";}
};
int main(int argc,char **argv)
{
_CrtMemState state;
_CrtMemCheckpoint(&state);
Base *t =new Final;
t->test();
delete t;
_CrtMemState state2, stateDiff;
_CrtMemCheckpoint(&state2);
_CrtMemDumpAllObjectsSince(&state);
_CrtMemDifference(&stateDiff, &state, &state2);
_CrtMemDumpStatistics(&stateDiff);
}
-----------------------------------------------------------------------
-----------------------------------------------------------------------
This results in the following debug output:
-----------------------------------------------------------------------
-----------------------------------------------------------------------
Dumping objects ->
{45} normal block at 0x00323E70, 32 bytes long.
Data: <0123456789012345> 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
35
Object dump complete.
0 bytes in 0 Free Blocks.
32 bytes in 1 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 0 bytes.
Total allocations: 64 bytes.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
Thus I have a 32 bytes leak per call. Two more observations:
1. When changing the code from
Base *t =new Final;
to
Final *t =new Final;
the problem is resolved - no leak anymore.
2. When the string "0123456789012345" is less than 16 bytes long, the
leak disappears and the longer it becomes, the larger the leak.
I would like to know if anyone can reproduce this problem and if there
is a known workaround. I already had a short look at the MSKB but did
not find anything at once.
Thanks in advance for any help,
Daniel
Daniel:
Classes used as base class should always have virtual destructor. You
just found out why.
In your case, when string is less than 16 characters, no memory is
allocated on the heap (short string optimization, I think it is called).
David Wilkinson