Memory Leaks

Recommended Posts

HJSimpson    122
I have a question about memory leaks. My program declares an instance of a class in the main function. This class contains several objects that need to be cleaned up when the class is destroyed. So, the code to clean it up is located in the destructor, which is called when the instance goes out of scope. But, it doesn't go out of scope until main is closed, which is after the program has exited. Therefore, one the destructor is called, it throws an access violation. So, is this correct, and is it a problem?

Share on other sites
Mmm.

The deconstructor should get called at the end of the program, and it should not throw an access violation (atleast, it does not when I do what your doing [if I understand you correctly]). Might I suggest you try Debugging it? Other then that, some code might help.

Share on other sites
GotenRulezU    100
have you tried calling the destructor before your program closes?
I.E. class.~class();?
hope that works.
=-Cory-=

Share on other sites
Samurai Jack    455
I had the same problem with singletons. Make a debug function in your singleton class:

in contructor you should have something like this:

CSingleton::CSingleton()
{
m_pSingleton = this;
etc...
}

make something like this:

static void dbgDestroy(void)
{
if(m_pSingleton != NULL)
{
delete m_pSingleton;
m_pSingleton = NULL;
}
}

in the last line of code, before you call _CrtDumpMemoryLeaks insert:

CSingleton::dbgDestroy(); <- Leaves the scope
_CrtDumpMemoryLeaks();

Beware, you have to create your singleton with "new" in order to be able to destroy it whenever you want.

Share on other sites
Zahlman    1682
0) DO NOT CALL THE DESTRUCTOR EXPLICITLY. You would only do this if you "called the constructor explicitly" (a simplification) as well, via 'placement new'. Anything else is serious bad mojo in the undefined behaviour sense.

1) The question as posed is not about memory leaks, and if the destructor throws an access violation, the problem is with the code of the destructor.

I *think* what you meant is that you have put in some kind of memory leak detection, which you call at the end of main(), and it trips an assertion saying "omg memory leak" because the object hasn't been destructed yet (because main() hasn't ended yet).

This is correct behaviour, and is not "a problem" unless you want accurate detection of leaks. But I assume you do :)

The simplest solution is probably to make use of an anonymous scope:

int main() {  { // <-- you don't need any if/for/while/etc. construct in order to introduce    // a new level of scope!    ThingWithComplexDestructor x;    do_lots_of_stuff();  } // <-- this is the end of x's scope, so its destructor is called here  detect_memory_leaks(); // <-- assuming the destructor works properly,  // there should be no leak detected here.}

The provided solution for singletons is really only relevant if you have a static or global object that needs to be destructed. Even then, you may consider instantiating the global object as a local of main(), and exposing a global *pointer to main's variable*. Then, client code accesses the singleton via the global pointer, and the singleton's dtor is called as a result of the object falling out of its scope (the anonymous scope within main()).

Share on other sites
HJSimpson    122
It uses SDL_ttf to draw text to the screen. I tried calling the destructor befor the end of the program, which prevented it from causing access violations, but caused the program to not exit ie return a value and cause the debugger to stop. When I put nothing into the destructor, no access violations.

I also tried adding an extra scope inside main which contains everything except for return 0; So the problem may be something else

The relevant code:
#include "SDL\SDL.h"#include "SDL\SDL_ttf.h"#include "Text.h"int main(int argc, char* argv[]){	SDL_Surface *screen;	SDL_Event e;	bool running;	Text text;	if(SDL_Init(SDL_INIT_VIDEO)<0)	{		return 1;	}	if(TTF_Init()<0)	{		return 1;	}		screen=SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);		if(screen==NULL)	{		return 1;	}	SDL_WM_SetCaption("Testing", NULL);	/**OBJECT INITIALIZATION**/		text.Load(".\\fonts\\vera.ttf", 16);	text.SetText("testing");	text.SetColour(255, 0, 0);	/**LOOP**/	running=true;	while(running)	{		/**DRAWING**/		text.Write(screen);		SDL_Flip(screen);		/**EVENT HANDLER**/		SDL_PollEvent(&e);		switch(e.type)		{		case SDL_QUIT:			running=false;			break;		case SDL_KEYUP:			switch(e.key.keysym.sym)			{			case SDLK_ESCAPE:				running=false;				break;			}//end keysymbol handler		}//end event handler	}//end loop	SDL_FreeSurface(screen);	SDL_Quit();	TTF_Quit();	return 0;}destructor for text:Text::~Text(){	SDL_FreeSurface(txtSurface);	TTF_CloseFont(font);}member variables for text:TTF_Font *font;std::string text;SDL_Rect destRect;SDL_Colour fontColour;SDL_Surface *txtSurface;

Share on other sites
dmail    116
Ok without trying to sound rude I really wish people would read the sdl docs. You do not own the SDL_surface which is created by SDL_SetVideoMode and you should not clean it up using SDL_FreeSurface.
Quote:
 ... The surface returned is freed by SDL_Quit and should not be freed by the caller. Note: This rule includes consecutive calls to SDL_SetVideoMode (i.e. resize or rez change) - the pre-existing surface will be released automatically.

http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fSetVideoMode

Share on other sites
SiCrane    11839
int main(int argc, char* argv[]){	if(SDL_Init(SDL_INIT_VIDEO)<0)        // blah blah all the other initializers        {        	Text text;                // all the other stuff        }	SDL_FreeSurface(screen);	TTF_Quit();	SDL_Quit();	return 0;}

Share on other sites
HJSimpson    122
Thanks for the help, adding the second scope and eliminating the SDL_FreeSurface(screen) fixed it.

Share on other sites
Zahlman    1682
Quote:
 Original post by HJSimpsonIt uses SDL_ttf to draw text to the screen. I tried calling the destructor befor the end of the program, which prevented it from causing access violations, but caused the program to not exit ie return a value and cause the debugger to stop. When I put nothing into the destructor, no access violations.

Then the access violation is nothing to do with a "memory leak" (that's forgetting to clean up something you should) and is a plain old access violation having to do with double-deletion (that's trying to clean up something again when you shouldn't) - a side effect of the SDL_FreeSurface() call on something you're not supposed to SDL_FreeSurface().