TTF memory vacuum

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

TTF memory vacuum

Post 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?
User avatar
Bakkon
Chaos Rift Junior
Chaos Rift Junior
Posts: 384
Joined: Wed May 20, 2009 2:38 pm
Programming Language of Choice: C++
Location: Indiana

Re: TTF memory vacuum

Post 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.
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Re: TTF memory vacuum

Post 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();
	}
}
User avatar
dani93
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 38
Joined: Mon Apr 13, 2009 9:38 am
Location: Austria

Re: TTF memory vacuum

Post 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.
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Re: TTF memory vacuum

Post 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?
User avatar
Bakkon
Chaos Rift Junior
Chaos Rift Junior
Posts: 384
Joined: Wed May 20, 2009 2:38 pm
Programming Language of Choice: C++
Location: Indiana

Re: TTF memory vacuum

Post 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.
User avatar
dani93
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 38
Joined: Mon Apr 13, 2009 9:38 am
Location: Austria

Re: TTF memory vacuum

Post 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!
User avatar
hurstshifter
ES Beta Backer
ES Beta Backer
Posts: 713
Joined: Mon Jun 08, 2009 8:33 pm
Favorite Gaming Platforms: SNES
Programming Language of Choice: C/++
Location: Boston, MA
Contact:

Re: TTF memory vacuum

Post 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!
"Time is an illusion. Lunchtime, doubly so."
http://www.thenerdnight.com
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Re: TTF memory vacuum

Post 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?
Live-Dimension
Chaos Rift Junior
Chaos Rift Junior
Posts: 345
Joined: Tue Jan 12, 2010 7:23 pm
Favorite Gaming Platforms: PC - Windows 7
Programming Language of Choice: c++;haxe
Contact:

Re: TTF memory vacuum

Post 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
Image
User avatar
Bakkon
Chaos Rift Junior
Chaos Rift Junior
Posts: 384
Joined: Wed May 20, 2009 2:38 pm
Programming Language of Choice: C++
Location: Indiana

Re: TTF memory vacuum

Post 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);
      }
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: TTF memory vacuum

Post 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.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: TTF memory vacuum

Post 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
Image
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: TTF memory vacuum

Post 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.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
Post Reply