Page 1 of 1

TTF memory vacuum

Posted: Sun Feb 21, 2010 9:35 am
by RandomDever
So my game has hit a stand still because when you run the program for like 5 seconds the memory goes to 100,000k of usage. it fluctuates alot but it's not a memory leak. A memory leak would only go up in a linear fashion right? Anyways I've heard that some people have this problem when rendering changing text every frame because of the TTF library. Does anyone know how to fix it?

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 2:57 pm
by Bakkon
I had a problem like this once because every frame I was opening the font I was using and then not closing it. Can't say much else without seeing some code.

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 3:07 pm
by RandomDever
Bakkon wrote:I had a problem like this once because every frame I was opening the font I was using and then not closing it. Can't say much else without seeing some code.

Code: Select all

void StateManager::DrawState()
{
	if( state == MAIN_MENU )
	{
		SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0, 0, 0 ) );
		//TTF_SetFontStyle( comicsans, TTF_STYLE_UNDERLINE );
		title = TTF_RenderText_Solid( comicsans, "_________", orange );
		ApplySurface( 320 - ( title->clip_rect.w / 2 ), 50, title, screen );
		//TTF_SetFontStyle( comicsans, TTF_STYLE_NORMAL );
		title = TTF_RenderText_Solid( comicsans, "DUCK HUNT", cyan );
		ApplySurface( 320 - ( title->clip_rect.w / 2 ), 50, title, screen );
		screen = TTF_RenderCenteredText_Solid( arial, "Start!", white, startDuckHunt.button, screen );
		ApplySurface( 272, 224, startDuckHunt.GetImage(), screen, startDuckHunt.nextClip );
		screen = TTF_RenderCenteredText_Solid( arial, "High Scores", white, highScores.button, screen );
		ApplySurface( 272, 258, highScores.GetImage(), screen, highScores.nextClip );
		highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[0].c_str(), white );
		ApplySurface( screen->clip_rect.w / 2 - highestScore->clip_rect.w / 2, 430, highestScore, screen );
		SDL_Flip( screen );
	}
	if( state == DUCK_HUNT )
	{
		SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0, 0, 0 ) );
		ApplySurface( 0, 410, gUI, screen );
		ApplySurface( 30, 415, gUIShot, screen );
		switch( shotsRemaining )
		{
		case 1: ApplySurface( 15, 440, gUIBullet, screen ); break;
		case 2: ApplySurface( 15, 440, gUIBullet, screen ); ApplySurface( 42, 440, gUIBullet, screen ); break;
		case 3: ApplySurface( 15, 440, gUIBullet, screen ); ApplySurface( 42, 440, gUIBullet, screen ); ApplySurface( 70, 440, gUIBullet, screen ); break;
		}
		gUIPoints = TTF_RenderText_Solid( arialLarge, scoreBuf.c_str(), white );
		if( atoi( scoreBuf.c_str() ) != score )
		{
			scoreBuf = intToString( score );
		}
		ApplySurface( 120, 415, gUIHit, screen );
		ApplySurface( 555, 415, gUIScore, screen );
		ApplySurface( 543, 435, gUIPoints, screen );
		SDL_Flip( screen );
	}
	if( state == HIGH_SCORES )
	{
		SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0, 0, 0 ) );
		if( score > (unsigned int)atoi( scores[1].c_str() ) )
		{
			SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 128, 128, 255 ) );
			name.Show( 250, 380, screen, false );
		}
		highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[0].c_str(), white );
		ApplySurface( 250, 40, highestScore, screen );
		highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[1].c_str(), white );
		ApplySurface( 250, 100, highestScore, screen );
		highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[2].c_str(), white );
		ApplySurface( 250, 160, highestScore, screen );
		highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[3].c_str(), white );
		ApplySurface( 250, 220, highestScore, screen );
		highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[4].c_str(), white );
		ApplySurface( 250, 280, highestScore, screen );
		screen = TTF_RenderCenteredText_Solid( arial, "Back", white, back.button, screen );
		ApplySurface(20, 444, back.GetImage(), screen, back.nextClip );
		SDL_Flip( screen );
	}
}
void StateManager::SoundState()
{
	if( state == MAIN_MENU )
	{
	}
}
void StateManager::EventState()
{
	if( state == MAIN_MENU )
	{
		time = SDL_GetTicks();
		previousState = MAIN_MENU;
		while( SDL_PollEvent( &event ) )
		{
			if( startDuckHunt.Check( event ) )
			{
				state = DUCK_HUNT;
				SDL_WM_SetCaption( "Duck Hunt", NULL );
				SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0, 0, 0 ) );
			}
			if( highScores.Check( event ) )
			{
				back.Reset();
				state = HIGH_SCORES;
				SDL_WM_SetCaption( "High Scores", NULL );
				SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0, 0, 0 ) );
			}
			if( event.type == SDL_QUIT )
			{
				quit = true;
			}
		}
		stateManager.DrawState();
		while( framesPerSecond / 1000 > SDL_GetTicks() - time )
		{
		}
	}
	if( state == DUCK_HUNT )
	{
		time = SDL_GetTicks();
		previousState = DUCK_HUNT;
		while( SDL_PollEvent( &event ) )
		{
			if( event.type == SDL_KEYDOWN )
			{
				if( event.key.keysym.sym == SDLK_TAB )
				{
					back.Reset();
					state = HIGH_SCORES;
				}
			}
			if( event.type == SDL_QUIT )
			{
				quit = true;
			}
		}
		stateManager.DrawState();
	}
	if( state == HIGH_SCORES )
	{
		time = SDL_GetTicks();
		while( SDL_PollEvent( &event ) )
		{
			if( score > (unsigned int)atoi( scores[1].c_str() ) && previousHuntState == GAME_OVER )
			{
				if( event.type == SDL_KEYDOWN )
				{
					name.HandleInput( event, arcadeclassic, white );
				}
				if( name.GetString().length() == 3 && score > (unsigned int)atoi( scores[1].c_str() ) )
				{
					newHighScore( name.GetString().c_str(), score );
				}
			}
			if( back.Check( event ) )
			{
				state = previousState;
				highScores.Reset();
				startDuckHunt.Reset();
			}
			if( event.type == SDL_QUIT )
			{
				quit = true;
			}
		}
		stateManager.DrawState();
	}
}

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 3:25 pm
by dani93
You render surfaces but you don't free the memory.
http://jcatki.no-ip.org:8080/SDL_ttf/SD ... html#SEC43
Quote of the most important part:
The caller (you!) is responsible for freeing any returned surface.

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 3:38 pm
by RandomDever
dani93 wrote:You render surfaces but you don't free the memory.
http://jcatki.no-ip.org:8080/SDL_ttf/SD ... html#SEC43
Quote of the most important part:
The caller (you!) is responsible for freeing any returned surface.
So I'm supposed to free the surfaces before the program quits?

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 4:09 pm
by Bakkon
When you call TTF_RenderText_Solid, you are creating memory for an SDL_Surface, so you need to free that memory once you're done.

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 4:25 pm
by dani93
RandomDever wrote:
dani93 wrote:You render surfaces but you don't free the memory.
http://jcatki.no-ip.org:8080/SDL_ttf/SD ... html#SEC43
Quote of the most important part:
The caller (you!) is responsible for freeing any returned surface.
So I'm supposed to free the surfaces before the program quits?
Simple: Free them when you don't need them anymore.
I assume this function gets called in a loop. So you reassign new surfaces everytime the function is called. The previously assigned surfaces are lost, but they still exist in memory (-> memory leak). So you need to free them when the function quits or even better right after blitting it the last time. Because you use the same pointer for several surfaces you will need to free each of them, not only the last!

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 7:46 pm
by hurstshifter
This thread just lead me to the source of a leak that I had in one of my program I had as well. The ttf's were the last place I thought to look. Sweet!

Re: TTF memory vacuum

Posted: Sun Feb 21, 2010 10:38 pm
by RandomDever
dani93 wrote: Because you use the same pointer for several surfaces you will need to free each of them, not only the last!
:shock:




How?

Re: TTF memory vacuum

Posted: Mon Feb 22, 2010 5:55 am
by Live-Dimension
RandomDever wrote:
dani93 wrote: Because you use the same pointer for several surfaces you will need to free each of them, not only the last!
:shock:
How?
By deleteing (delete SurfacePtr; ) each unused surface before reassigning the pointer.
I think you should brush up on pointers before you use them any further.
http://www.cplusplus.com/doc/tutorial/pointers/

A basic understanding of pointers is a MUST if you plan to use them to avoid the very issues your having :P

Re: TTF memory vacuum

Posted: Mon Feb 22, 2010 7:02 am
by Bakkon

Code: Select all

      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[0].c_str(), white );
      ApplySurface( 250, 40, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[1].c_str(), white );
      ApplySurface( 250, 100, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[2].c_str(), white );
      ApplySurface( 250, 160, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[3].c_str(), white );
      ApplySurface( 250, 220, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[4].c_str(), white );
      ApplySurface( 250, 280, highestScore, screen );
This part of your code can be fixed and condensed by doing this...

Code: Select all

      for(int i = 0; i < 5; i++)
      {
            highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[i].c_str(), white );
            ApplySurface( 250, i * 60 + 40, highestScore, screen );
            SDL_FreeSurface(highestScore);
      }

Re: TTF memory vacuum

Posted: Tue Feb 23, 2010 2:07 am
by short
Bakkon wrote:

Code: Select all

      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[0].c_str(), white );
      ApplySurface( 250, 40, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[1].c_str(), white );
      ApplySurface( 250, 100, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[2].c_str(), white );
      ApplySurface( 250, 160, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[3].c_str(), white );
      ApplySurface( 250, 220, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[4].c_str(), white );
      ApplySurface( 250, 280, highestScore, screen );
This part of your code can be fixed and condensed by doing this...

Code: Select all

      for(int i = 0; i < 5; i++)
      {
            highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[i].c_str(), white );
            ApplySurface( 250, i * 60 + 40, highestScore, screen );
            SDL_FreeSurface(highestScore);
      }
However if his compiler does not unwind this when it optimizes the code he would be slowing his code down. Just sayin.

Re: TTF memory vacuum

Posted: Tue Feb 23, 2010 9:51 pm
by eatcomics
short wrote:However if his compiler does not unwind this when it optimizes the code he would be slowing his code down. Just sayin.
Disregard this, bakkon's is much better

Re: TTF memory vacuum

Posted: Tue Feb 23, 2010 10:07 pm
by dandymcgee
short wrote:
Bakkon wrote:

Code: Select all

      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[0].c_str(), white );
      ApplySurface( 250, 40, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[1].c_str(), white );
      ApplySurface( 250, 100, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[2].c_str(), white );
      ApplySurface( 250, 160, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[3].c_str(), white );
      ApplySurface( 250, 220, highestScore, screen );
      highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[4].c_str(), white );
      ApplySurface( 250, 280, highestScore, screen );
This part of your code can be fixed and condensed by doing this...

Code: Select all

      for(int i = 0; i < 5; i++)
      {
            highestScore = TTF_RenderText_Solid( arcadeclassic, scoresList[i].c_str(), white );
            ApplySurface( 250, i * 60 + 40, highestScore, screen );
            SDL_FreeSurface(highestScore);
      }
However if his compiler does not unwind this when it optimizes the code he would be slowing his code down. Just sayin.
I'm pretty sure any decent compiler is going to be much more successful at optimizing a for loop than magically realizing 50 lines of code are different by 1 number.