(impossible?) Memory leak problem

Started by
15 comments, last by alvaro 11 years, 5 months ago
AKA, meaning "Also Known As", implies that "static" and "global" are the same. Your usage of "i.e.", which means "that is", says that all globals are class variables, which is also not true. You should use "e.g." meaning "for example".


First smirk of the day award goes to rip-off.


This is an interesting problem with static variables. Since you call CrtDumpMemoryLeaks() before main() exits, static variables which allocate memory (which get destructed after main() exits) will still show as memory leaks. To avoid this false positive, don't call CrtDumpMemoryLeaks() manually. The _CRTDBG_LEAK_CHECK_DF flag effectively adds the memory leak dump as an atexit() call, which happens at the very end of the program.


This. I was about to look up the function there because I suspected that this was the case.

Memory leak detectors work by reporting on anything that's still allocated when they are invoked (they hook the allocation and deallocation functions to keep track). So if you're calling the function prior to the end of the program then anything that's still allocated will be reported on.

I'd also recommend checking out VLD. Someone here suggested it to me and I tried it and love it. You can just double-click the message in the report to go straight to the leaky allocation in the code.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
Advertisement
Thanks guys. Good to know :)
No one really saw it? Really???

There's a lot that goes on after leaving main(); hence why it's telling you there are leaks.
Try using atexit.

Personally, I prefer to create a static object, ensure it's the first one to get created, and then let the C++ compiler clean up last:

[source lang="cpp"]class MeFirst
{
MeFirst() {}
~MeFirst() { /* -- call CRT debug dump here -- */ }
static MeFirst& getSingleton()
{
static MeFirst instance;
return instance;
}
}

int main()
{
//Calling first may ensure the static initialization goes first.
volatile MeFirst &doThisFirst = MeFirst::getSingleton();
return 0;
}[/source]

It's out of my head, and beware I may be missing a case where another static variable gets initialized before this one, hence you may still get leaks (before it will be destroyed after CRT dump). Anyway, try different approaches, google a little, experiment, and find out how to make the CRT Dump get truly called last.
wxWidgets manages to do it correctly, you may want to take a look there.

Cheers
Dark Sylinc

Edit: Oh, and Singleton is an evil pattern. Don't use it. This is an exception because you're not actually using it.
Why would you use a singleton to implement something that doesn't need implemented?

The _CRTDBG_LEAK_CHECK_DF flag effectively adds the memory leak dump as an atexit() call,


Additionally, there's absolutely no guarantee that instantiating 'first' will make that object deconstruct last. Additionally, if he's getting leaks from just including a header file then obviously he's got something doing allocations prior to main(), so being 'first' by instantiating in main isn't possible and there's explicitly no defined order for global or static initializations across compilation units.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

Additionally, there's absolutely no guarantee that instantiating 'first' will make that object deconstruct last.


Actually, I am pretty sure there is a guarantee that destruction of static objects will happen in the reverse order of construction (more precisely, the end of construction).
I misspoke. I meant in the context of the 'pre-main' objects.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

I misspoke. I meant in the context of the 'pre-main' objects.

I am not sure if you misspoke or you misunderstood: The static objects I am referring to are meant to contain what you call "pre-main" objects.

If I remember the rules correctly, within a translation unit (a .cpp file), global objects are constructed in the order they are defined, but there is no guarantee of what order things in different translation units will be constructed (which means there is no solution that guarantees your object will be "first", unless it's something specific the compiler provides). Static local variables are constructed on the first function call where they are needed (which could be as part of the construction of some other static object). Then destructors will be invoked in the reverse order of when the constructors finished.

As an example of how these guarantees can be useful, think of a program that has a singleton implementation of a log. If a global object wants to write something out to the log at destruction (statistics of usage or what have you), you need to make sure that the log gets destructed later than the global object. The global object can guarantee this by using the log from the constructor (all you need is something like Log::get_instance(), even if you do nothing with it). Then the log's constructor is guaranteed to have finished before the object's constructor, and destructors will be called in the right order.

DISCLAIMER: After one attempt at trying to be clever about these things, I decided that the advice to not use global variables of any type is golden, and I strongly discourage people from doing what I described in the paragraph above. Don't use global variables, or singletons, or static local variables, or static member data, and you'll save yourself some really bad headaches.

This topic is closed to new replies.

Advertisement