Sign in to follow this  
Sethcran

SDL TTF unhandled exception

Recommended Posts

I recently started a new project, and am still early on, but came across an error on attempting to close the window that I have so far, and I can't quite figure out what is causing it or how to fix it, and was hoping that someone here might have some advice or hints as to what exactly the problem is. I'll give all the code that should be relavent to the problem, but if I forget something, I can provide it. I'm getting an unhandled exception, an access violation on the line with TTF_CloseFont( font ); in the destructor.
Surface::~Surface()
{
	if ( surface != NULL )
		SDL_FreeSurface( surface );
	if ( font != NULL )
		TTF_CloseFont( font );
}
Now normally, I figure this to mean that the font failed to open for whatever reason, but here is the code I have that opens it:
Surface::Surface( std::string fileName, int size )
{
	font = NULL;
	font = TTF_OpenFont( fileName.c_str(), size );
	assert( font != NULL );

	SDL_Color color = { RED, GREEN, BLUE, ALPHA };
	textColor = color;

	surface = NULL;
}
which is called via:
Driver::Driver() :
	font( FONT_LOCATION, FONT_SIZE )
where FONT_LOCATION and size are as follows.
const std::string FONT_LOCATION = "data\\Calibri.ttf";
const int FONT_SIZE = 18;
I know for sure that the files are in the correct place, and that the address is correct. As far as I know, the TTF_OpenFont will return NULL on an error, which would cause my code not to lead to an unhandled exception, meaning it is loading something, if not correctly. Any ideas what I'm missing? I'm sure it's something small and obvious right in front of my face, but I just can't seem to figure it out at the moment. If you need to see any more code just ask and I can post what I have so far. Thanks for the replies <3

Share this post


Link to post
Share on other sites
Do you have a copy constructor and operator=()? If not, then that's quite possibly your problem; you could assign one font from another, and then let the original go out of scope. The second font would be just bit copied from the first, and then when the first goes out of scope its destructor invalidates the pointer.

Share this post


Link to post
Share on other sites
Set your pointers surface and font equal to NULL in your surface destructor. If that fixes/moves the error I would guess you are deleting a surface more than once.

Just my first guess.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Do you have a copy constructor and operator=()? If not, then that's quite possibly your problem; you could assign one font from another, and then let the original go out of scope. The second font would be just bit copied from the first, and then when the first goes out of scope its destructor invalidates the pointer.



I do not, but the font and surface variables are simply pointers of the TTF_Font* and SDL_Surface* types. So this seems unecessary, at least at this point. The font shouldn't go out of scope until the object itself is deleted, which occurs upon closing the program.

Quote:

Set your pointers surface and font equal to NULL in your surface destructor. If that fixes/moves the error I would guess you are deleting a surface more than once.

Just my first guess.


Tried, but nothing. The destructor here is the only point where I am deleting any surfaces, as I am trying to set this up in a RAII fashion.

Current Surface header:


#ifndef SURFACE_H
#define SURFACE_H

#include <string>
#include "SDL.h"
#include "SDL_ttf.h"

const int RED = 255, GREEN = 0, BLUE = 0, ALPHA = 0; // Color to render text, currently red.
const Uint8 CCRED = 255, CCGREEN = 255, CCBLUE = 255; // Color to be transparent in images, currently White.

class Surface
{
public:
Surface();
Surface( std::string fileName ); // Load image surface.
Surface( std::string fileName, int size ); // Load font surface.
~Surface();
void Apply( int x, int y, SDL_Surface* source, SDL_Rect* clip );
SDL_Surface* GetSurface();
void SetSurface( SDL_Surface* s );
TTF_Font* GetFont();

private:
SDL_Surface* surface;
TTF_Font* font;
SDL_Color textColor;

};
#endif

Share this post


Link to post
Share on other sites
Is it possible you are copying the class by mistake? Get any errors if you make the surface class' assignment operator and copy constructor private?

Share this post


Link to post
Share on other sites
Quote:
Original post by Wolfdog
Is it possible you are copying the class by mistake? Get any errors if you make the surface class' assignment operator and copy constructor private?


Not that I know of. I'll post pretty much the entire code I have so far ( it's not much, I only just started ).

main.cpp

#include <string>
#include <assert.h>
#include "SDL.h"
#include "SDL_ttf.h"
#include "surface.h"
#include "driver.h"

const std::string CAPTION = "Break Out!";

void InitializeSDL();
void QuitSDL();


int main( int argc, char* args[] )
{
InitializeSDL();

Driver game;

while ( !game.Quit() )
{
game.Events();
game.Logic();
game.Render();
}

QuitSDL();

return 0;
}





void InitializeSDL()
{
assert ( SDL_Init( SDL_INIT_EVERYTHING ) == 0 );
assert ( TTF_Init() == 0 );

SDL_WM_SetCaption( CAPTION.c_str(), NULL );
}





void QuitSDL()
{
SDL_Quit();
TTF_Quit();
}


driver.h

#ifndef DRIVER_H
#define DRIVER_H

#include "surface.h"
#include <string>

const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

const std::string FONT_LOCATION = "data\\Calibri.ttf";
const int FONT_SIZE = 18;

class Driver
{
public:
Driver();
~Driver();
void Events();
void Logic();
void Render();
bool Quit();

private:
void ProcessKeyEvents();
bool quit;
SDL_Color textColor;
Surface screen;
Surface font;

};
#endif


driver.cpp

#include "driver.h"

Driver::Driver() :
font( FONT_LOCATION, FONT_SIZE )
{
quit = false;

screen.SetSurface( SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE ) );
}





Driver::~Driver()
{
}





void Driver::Events()
{
SDL_Event input;
while ( SDL_PollEvent( &input ) )
{
if ( input.type == SDL_QUIT )
quit = true;
if ( input.type == SDL_KEYDOWN )
ProcessKeyEvents();
}
}





void Driver::Logic()
{
}





void Driver::Render()
{
SDL_FillRect( screen.GetSurface(), NULL, SDL_MapRGB( screen.GetSurface()->format, 0xFF, 0xFF, 0xFF ) ); // Fill screen white.
SDL_Flip( screen.GetSurface() );
}





bool Driver::Quit()
{
return quit;
}





void Driver::ProcessKeyEvents()
{
}


surface.h

#ifndef SURFACE_H
#define SURFACE_H

#include <string>
#include "SDL.h"
#include "SDL_ttf.h"

const int RED = 255, GREEN = 0, BLUE = 0, ALPHA = 0; // Color to render text, currently red.
const Uint8 CCRED = 255, CCGREEN = 255, CCBLUE = 255; // Color to be transparent in images, currently White.

class Surface
{
public:
Surface();
Surface( std::string fileName ); // Load image surface.
Surface( std::string fileName, int size ); // Load font surface.
~Surface();
void Apply( int x, int y, SDL_Surface* source, SDL_Rect* clip );
SDL_Surface* GetSurface();
void SetSurface( SDL_Surface* s );
TTF_Font* GetFont();

private:
SDL_Surface* surface;
TTF_Font* font;
SDL_Color textColor;

};
#endif


surface.cpp

#include "surface.h"
#include "SDL.h"
#include "SDL_image.h"
#include <assert.h>
#include <string>

Surface::Surface()
{
surface = NULL;
font = NULL;
}





Surface::Surface( std::string fileName )
{
SDL_Surface* loadedImage = NULL;

loadedImage = IMG_Load( fileName.c_str() );
assert( loadedImage != NULL );

surface = SDL_DisplayFormat( loadedImage );
SDL_FreeSurface( loadedImage );

Uint32 colorkey = SDL_MapRGB( surface->format, CCRED, CCGREEN, CCBLUE ); // Sets all white in the image to transparent

assert( surface != NULL );
SDL_SetColorKey( surface, SDL_SRCCOLORKEY, colorkey );

font = NULL;
}





Surface::Surface( std::string fileName, int size )
{
font = NULL;
font = TTF_OpenFont( fileName.c_str(), size );
assert( font != NULL );

textColor.b = BLUE;
textColor.g = GREEN;
textColor.r = RED;

surface = NULL;
}





Surface::~Surface()
{
if ( surface != NULL )
SDL_FreeSurface( surface );
if ( font != NULL )
TTF_CloseFont( font );
}





void Surface::Apply( int x, int y, SDL_Surface* source, SDL_Rect* clip )
{
/* Applies a surface source another labeled destination at the x,y coordinates
passed in. */

SDL_Rect offset;
offset.x = x;
offset.y = y;
assert ( SDL_BlitSurface( source, clip, surface, &offset ) != -1 );
}





SDL_Surface* Surface::GetSurface()
{
return surface;
}





void Surface::SetSurface( SDL_Surface* s )
{
surface = s;
}





TTF_Font* Surface::GetFont()
{
return font;
}


That is literally the extant of all I have done up until this problem, perhaps I'm overlooking something silly?

Share this post


Link to post
Share on other sites
Use source tags [ source ] [ /source ] (without the spaces) when posting code that large.


int main( int argc, char* args[] )
{
InitializeSDL();

{
Driver game;

while ( !game.Quit() )
{
game.Events();
game.Logic();
game.Render();
}
}

QuitSDL();

return 0;
}




That should fix your issue, game was going out of scope after you called QuitSDL().

Share this post


Link to post
Share on other sites
Didn't know about the source tags, I will remember that thanks.

And of course it was something simple, makes me feel like a dumbass now, lol. Thanks a bunch!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this