Sign in to follow this  

Very odd SDL error

This topic is 4181 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I ran into this error while I was testing my game engine for funtionality. Everything seemed fine, the program build with no errors. Then when I ran the program, the window just quickly flashed and disapeared, the debug said it was an access violation. The problem seems to be when I call any member function that uses SDL member variables in it. If I take the line out that uses the SDL variable, the program runs. I have had these access violation errors before and fixed all of them except this one. If anyone knows how to fix this error please tell me. Thanks.

Share this post


Link to post
Share on other sites
Sorry about not coming back to this thread. Ok, here is the code for you.

It seems to occur because I'm trying to access the classes own member variables (like string ID), but that can't be right, there has got to be another cause.

**************
Tile.h file
**************

//include guards
#ifndef __TILE_H__
#define __TILE_H__

#include "sdl.h"
#include "stdlib.h"
#include "string"
#include "graphics.h"

using namespace std;

class CTile
{
private:
CGraphics TileImage;
string ID;
SDL_Rect TileRect;
int Type;
int x;
int y;

public:
void MakeTile(string id, int xpos, int ypos, int type);
void DisplayTile(SDL_Surface *displaysurface);
int GetType();
int GetX();
int GetY();
void SetType(int type);
void SetX(int xpos);
void SetY(int ypos);
};

#endif


******************
Tile.cpp file
******************

#include "tile.h"

int CTile::GetType()
{
return Type;
}

int CTile::GetX()
{
return x;
}

int CTile::GetY()
{
return y;
}

void CTile::SetType(int type)
{
Type = type;
}
void CTile::SetX(int xpos)
{
x = xpos;
}

void CTile::SetY(int ypos)
{
y = ypos;
}

void CTile::MakeTile(string id, int xpos, int ypos, int type)
{
/*
this function is where acces violation happens
*/
ID = id;
SDL_Surface *Tile;
Tile = TileImage.GetImage(ID);
TileRect.w = Tile->w;
TileRect.h = Tile->h;
TileRect.x = xpos;
TileRect.y = ypos;
Type = type;
SDL_FreeSurface(Tile);
}

void CTile::DisplayTile(SDL_Surface *displaysurface)
{
SDL_Surface *Tile;
Tile = TileImage.GetImage(ID);
SDL_BlitSurface(Tile, NULL, displaysurface, &TileRect);
SDL_FreeSurface(Tile);
}

Share this post


Link to post
Share on other sites
Post the code from your main(). I think the problem might be that you are trying to use the SDL variables before SDL has been init'ed. Either than that, go through it with a debugger, and/or comment out each line to see what happens (it seems liek you already did this, which is good, but do it again).

One more thing, a little of topic. In the function:

Quote:

void CTile::MakeTile(string id, int xpos, int ypos, int type)
{
/*
this function is where acces violation happens
*/
ID = id;
SDL_Surface *Tile;
Tile = TileImage.GetImage(ID);
TileRect.w = Tile->w;
TileRect.h = Tile->h;
TileRect.x = xpos;
TileRect.y = ypos;
Type = type;
SDL_FreeSurface(Tile);
}


You allocate and load the "Tile" surface, but then delete it after only getting the width and height. Later on, in your draw function, you reallocate it to draw. This can lead to a significant performance hit, and "might" be the cause of your problem. Consider just having a pointer.

Share this post


Link to post
Share on other sites
Quote:

void CTile::MakeTile(string id, int xpos, int ypos, int type)
{
/*
this function is where acces violation happens
*/
ID = id;
SDL_Surface *Tile;
Tile = TileImage.GetImage(ID);
TileRect.w = Tile->w;
TileRect.h = Tile->h;
TileRect.x = xpos;
TileRect.y = ypos;
Type = type;
SDL_FreeSurface(Tile);
}

If you're sure that's where the access violation is occurring then it's that TileImage.GetImage(ID); is returning NULL.

May we see what CGraphics::GetImage(...) looks like?

Share this post


Link to post
Share on other sites
Ok, here is Graphics.h and Graphics.cpp. I think this is where the problem is.

************
Graphics.h
************
//include guards
#ifndef __GRAPHICS_H__
#define __GRAPHICS_H__

#include "sdl.h"
#include "stdlib.h"
#include "string"
#include "fstream"
#include "map"

using namespace std;

/*
This class is merely a conatianer for all the graphics
that need to be loaded into memory. The constructor
loads all the images from the specified file.
*/
class CGraphics
{
private:
//map container to hold all graphics
map<string, SDL_Surface*> GraphicsMap;

public:
//loads graphics into GraphicsMap container
CGraphics(string filename);
//returns an SDL_Surface within GraphicsMap
SDL_Surface* GetImage(string imageID);
};

#endif

************
Graphics.cpp
************
#include "stdlib.h"
#include "sdl.h"
#include "graphics.h"

CGraphics::CGraphics(string filename)
{
string ID;
string pathname;

for(int n = 0; n <= 27; n++)
{
ifstream graphicsfile(filename.c_str());
graphicsfile >> ID;
graphicsfile >> pathname;
GraphicsMap[ID] = SDL_LoadBMP(pathname.c_str());
}
}

SDL_Surface* CGraphics::GetImage(string imageID)
{
return(GraphicsMap[imageID]);
}

Share this post


Link to post
Share on other sites
You call SDL_FreeSurface in inappropriate places. It *deletes* a surface, and if you continue to use a pointer to it, that will screw up your program.
Also, the [] operator of std::map silently creates a new entry if the key is not found.
You'll be better off using something like

SDL_Surface* CGraphics::GetImage(string imageID)
{
if (GraphicsMap.find(imageId) != GraphicsMap.end()) return(GraphicsMap[imageID]);
else {
cerr << "Couldn't get image: " << imageID;
exit(1);
}
}

Share this post


Link to post
Share on other sites
Ahh, there we go...

Well, at first I thought GetImage() is the error because I thought that it actually loads an image from the harddisk each time it is called. But it doesn't - it returns a local image.

In that case, you are caling SDL_FreeSurface() on that image, which is local to CGraphics. The first time it is ok, but the second time the image is already deleted. So from here:

void CTile::MakeTile(string id, int xpos, int ypos, int type)
{
/*
this function is where acces violation happens
*/
ID = id;
SDL_Surface *Tile;
Tile = TileImage.GetImage(ID);
TileRect.w = Tile->w;
TileRect.h = Tile->h;
TileRect.x = xpos;
TileRect.y = ypos;
Type = type;
SDL_FreeSurface(Tile);
}

Take out the red part (SDL_FreeSurface(Tile);).

Now CGraphics should be the one who "frees" the surface, because it owns it (otherwise it turns into a memory leak).

Cheers, and good luck!

Note: Double underscores in the front of an identifier are a big no-no - they are reserved for the compiler and preprocessor. Instead, go with something like this:

#ifndef HEADER_NAME_H
#define HEADER_NAME_H

...

#endif /* HEADER_NAME_H */

Share this post


Link to post
Share on other sites
I tried everything you told me to try, but I am still getting this access violation. I tried commenting out parts of the MakeTile function, and found that with even "ID = id;" being the only thing it that function, it still gives the access violation. This makes no sense to me at all, is there anything else I could try? Maybe I should just post the rest of the source.

Also thanks for your help so far.

Share this post


Link to post
Share on other sites

This topic is 4181 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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