Skip to main content
GameDev.net gamedev.net
🔒 Locked

Access Violations

Started by caseyd Apr 12, 2006 at 1:17 AM 2 replies 700+ views
Original Post
caseyd
caseyd
I am getting a really weird access violation and I can't seem to find out how to fix it. I am using Visual Studio .net 2005, how can I find what is causing this? I've been messing around with a few different things, but it seems like the violation is also moving around with everything i've been trying. I don't know too much about using the debugger so any information in that regards would be much appreciated. I am looking more for how to find the cause of things like this than how to fix my exact problem, but basically in a nuthsell this is what I'm trying to do. I have a Image class that represents an image. This class works because I've used it before. Now I have another class GameGrid, that has a private variable declared as Image* m_background. Now when the constructor of GameGrid is called it initializes the Image member with an image to load. Now it seems like the m_background variable isn't keeping it's value for some reason. Here's the corresponding classes: Image.h

/*
Header file for Image Class
Represents a single bitmap.

*/

#ifndef _IMAGE_H
#define _IMAGE_H

#include "SDL.h"

#include "sdl_util.h"

class Image {

public:
	Image(const char* filename, bool trans);
	~Image();

	// draw, copies m_image to given surface and coordinates.
	void draw(SDL_Surface* dest, int x, int y);
	void draw(SDL_Surface* dest);

	void setCoords(int x, int y) {m_coords.x = x; m_coords.y = y; }

	int getWidth() { return m_width; }
	int getHeight() { return m_height; }

private:
	SDL_Surface* m_image;
	SDL_Surface* m_optimized;

	SDL_Rect m_coords;

	int m_width,
		m_height;

	bool m_transparent;

}; // end Image
#endif

Image.cpp


#include "Image.h"
#include <cstdlib>

Image::Image(const char* filename, bool trans)
{
	m_image = SDL_LoadBMP("background.bmp");

	if (m_image) {
		fprintf(stderr, "Image loaded successfully!!\n");
	}


	m_width = m_image->w;
	m_height = m_image->h;
	
	m_transparent = trans;

	if (trans) 
		SDL_SetColorKey(m_image, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(m_image->format, 0, 0, 0));
	
	
	// Convert the image to the display format
	//m_optimized = SDL_DisplayFormat(m_image);
	
	//freeSurface(m_image);
	//SDL_FreeSurface(m_image);
}

Image::~Image()
{
	freeSurface(m_image);
}

// Draws the whole image stored in m_image to dest surface at x and y
void Image::draw(SDL_Surface* dest, int x, int y)
{

	SDL_Rect rect;

	rect.x = x;
	rect.y = y;
	rect.w = rect.x + m_width;
	rect.h = rect.y + m_height;

	SDL_BlitSurface(m_optimized, NULL, dest, ▭);
}

void Image::draw(SDL_Surface* dest)
{
	SDL_Rect rect;

	rect.x = m_coords.x;
	rect.y = m_coords.y;
	rect.w = rect.x + m_width;
	rect.h = rect.y + m_height;

	SDL_BlitSurface(m_optimized, NULL, dest, ▭);
}

GameGrid.h

#ifndef _GAME_GRID_H
#define _GAME_GRID_H


#include "SDL.h"

#include "sigma/Image.h"
#include "sigma/sdl_util.h"

class GameGrid {

public:
	GameGrid();
	~GameGrid();

	void clear();
	void randomize();
	void draw(SDL_Surface* dest, int x, int y);

	bool isMouseOver() { return true; }
	void gridClicked() {}
	void swapTiles() {}

private:
	static const int GRID_X_SIZE = 4;
	static const int GRID_Y_SIZE = 4;

	int m_grid[GRID_X_SIZE][GRID_Y_SIZE];

	int m_gridX, m_gridY;

	Image* m_background;

	Image* m_tile;
	Image* m_empty;

};

#endif

GameGrid.cpp

#include "GameGrid.h"
#include <cstdlib>

GameGrid::GameGrid() 
{
	
	m_background = new Image("background.bmp", false);
	//m_tile = new Image("bluetile.bmp", false);

	clear();
}

GameGrid::~GameGrid()
{
	delete m_background;
	//delete m_tile;
}

void GameGrid::clear() 
{
	for (int x = 0; x <= 4; x++) {
		for (int y = 0; y <= 4; y++) {
			m_grid[x][y] = 1;
		}
	}
}

void GameGrid::randomize()
{
}

void GameGrid::draw(SDL_Surface* dest, int x, int y)
{
	if (!m_background) {
		fprintf(stderr, "m_background loaded.\n");
		exit(1);
	}

	m_background->draw(dest, x, y);

	for (int j = 0; j <= 4; j++) {
		for (int k = 0; k <= 4; k++) {
			if (m_grid[x][y] == 1) {
				//m_tile->draw(dest, (x * m_tile->getWidth()), (y * m_tile->getHeight())); 
			}
		}
	}
}


Sorry about all the code. Any information on how to proceed in tracking this bug down would be great. I've been working on it for a day or two now, and I am sure it's something really simple that I am missing. Thanks, Casey
Falken42
Falken42
Your GameGrid::clear() function is overwriting memory:
for (int x = 0; x <= 4; x++) {    for (int y = 0; y <= 4; y++) {        m_grid[x][y] = 1;    }}


You define the map size with GRID_X_SIZE and GRID_Y_SIZE set to 4, but your loop actually accesses five elements, from zero to four, including four.

Your draw() function also suffers from the same issue.

In regards to debugging, you were correct that your m_background variable is being overwritten. I would use the "single step" command (usually F10 within VS2005) to step through the constructor while watching the m_background in the Watch window. As soon as you step over clear(), you would be able to see that m_background had changed.
caseyd
caseyd
Yep I knew it was something stupid like that. Thanks for pointing it out to me. I looked at that class a few times and just didn't see it. I'll remember later on when I get the same sorts of errors to check my array bounds.
Falken42
Falken42
Just in case you didn't know, when you suspect a memory overwrite, you can also set a breakpoint on a memory location. In MetroWorks CodeWarrior this incredibly easy (just right click on a symbol in the source and select "Watchpoint"), but with MSVC it's a little more involved:

1) Insert a breakpoint somewhere in the source after the variable has been assigned, but before the memory overwrite happens.

2) Run the application.

3) When the breakpoint is hit, from the Debug menu, select "New Breakpoint" -> "New Data Breakpoint".

4) Enter the address of the memory you wish to add a breakpoint on. In your case, it would be "&m_background". (Note the address-of operator!) You can also position the cursor (or mouse left-click) on the symbol and MSVC will automatically pick up the symbol name. You still need to add the & sign yourself.

5) Update the Byte Count to be the size of the symbol. In this case, it would be 4.

6) Click OK.

7) Press F5 to run the application.

When m_background changes, MSVC will popup a window letting you know what happened and stop on the line after the change.

Unfortunately with MSVC, data breakpoints are only triggered if the memory contents actually change instead of triggering for any overwrite. For example, if your m_background was initialized to NULL and you set a data breakpoint on that, it would have to change from NULL to some other value in order to be triggered. If a memory overwrite just overwrites NULL to m_background, MSVC won't catch it.

Also note that MSVC won't automatically re-enable any data breakpoints between application runs. If you stop debugging and then restart, you must do this yourself since actual symbol locations can change between compiles, and MSVC only stores the address of the breakpoint, and not its actual symbol name.

Hope this helps in your debugging!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.