Jump to content
  • Advertisement
Sign in to follow this  
ryandaniels

SDL access violation problems

This topic is 3488 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

Windows vista, SDL version 1.2.13, C++, Visual studio express 2008 Well, this is my first real C++ program, obviously I've made lots of little programs to learn different parts of c++, but this is the first one that actually does a useful task; it is supposed to take an image, and either 1)rotate it a certain amount of degrees, or 2)create an animation of it rotating 360 degrees. I have finished the code up to making still frames, haven't started on the animation, but it will be pretty simple anyways. But, as you know, as I was debugging it, I ran into some problems I couldn't figure out how to solve.
Unhandled exception at 0x00a613ee in RotateV2.exe: 0xC0000005: Access violation writing location 0x002e0012.
I cleared up one such problem before, it being that I was trying to access a null pointer. But I can't seem to figure out why this one is happening. The really weird thing about this problem is that it "jumps" around my program (meaning it will just pop up at different lines), to places that make no sense, sometimes randomly. I mean, literally, randomly. A few times now, I ran the program in debug mode, and it crashed in one place, then I stop and ran it again, and crashed somewhere else (Which leads me to believe that it's a software side problem). But usually it just jumps when I change something. I'll do something to try and fix it, and then the problem will jump to a new spot, the weirdest example is that it sometimes jumps to places it really shouldn't be crashing at. Here's a screenshot of the first place it popped up at, and what I think to be the center of the problem. It (almost) always gives me the error on the second time I call putpixel(). Sometimes though, it runs through all 10000 pixels and instead crashes on SDL_Flip. screenshot 2 Here's the code, I've commented it up for you guys.
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "cmath"
#include <vector>
#include <string>

using std::vector;
using std::string;

struct XY{
	int x;
	int y;
};

class Rotate {

private:
	SDL_Surface *image;
	Uint32 pixel;

	Uint32 getpixel(SDL_Surface *surface, int x, int y);
	void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
	XY CalculateRotation(XY old_coordinates, int degreechange, int &diagonal_length);
	
	

public:

	SDL_Surface *still;
	vector <SDL_Surface *> animation;


	Rotate(string name);

	void StillFrame(int degreechange);

	void Animation(int degreechange);

};


//first function

Uint32 Rotate::getpixel(SDL_Surface *surface, int x, int y){

	int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        return *p;

    case 2:
        return *(Uint16 *)p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return *(Uint32 *)p;

    default:
        return 0;       /* shouldn't happen, but avoids warnings */
    }


}


//next function

void Rotate::putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {

	int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        *p = pixel; //crashes on second time through here, usually
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }


}


//next function

//takes coordinates and rotates them around the center of the picture "degreechange" degrees
XY Rotate::CalculateRotation(XY old_coordinates, int degreechange, int &diagonal_length) {
	XY center; center.x= image->w/2; center.y= image->h/2;
	

	//This translates coordinates from being measured 
	//left to right and top to bottom to being measured from the center of the image
	//I use "a" and "b" because I use them with the pythagorean theorem a^2 + b^2 = c^2
	int a= (0- (center.x- old_coordinates.x ) );
	int b= (0+ (center.y- old_coordinates.y ) );

	double hypotenuse= sqrt(  (double)( a*a + b*b)  );
	double currentdegree= (asin(b/hypotenuse)) * 180/3.14;

	//finds what quadrant the point is in
	int quadrant;
	if( (a < 0) && (b < 0) )
		quadrant= 3;
	else if(a < 0)
		quadrant= 2;
	else if(b < 0)
		quadrant= 4;
	else quadrant= 1;


	//changes the degree based on degreechange
	//checks to see if the new point is in a different quadrant, and acts accordingly
	double newdegree;
	if( (quadrant == 2) || (quadrant == 4) ) {
		newdegree= currentdegree+degreechange;

		if(newdegree > 90) {
			quadrant--;
			newdegree= 180-newdegree;
		}
	}
	else {
		newdegree= newdegree-degreechange;

		if(newdegree < 0) {
			quadrant--;
			newdegree= 90+newdegree;
		}
		if (quadrant == -1)
			quadrant= 4;
	}

	//calculates the new coordinates using cosine and sine
	a= cos(newdegree)*hypotenuse;
	b= sin(newdegree)*hypotenuse;

	//gives the new coordinates proper negitive/positve values based on quadrant
	if(quadrant == 4)
		b*= -1;
	else if(quadrant == 3) {
		a*= -1;
		b*= -1;
	}
	else if(quadrant == 2)
		a*= -1;

	//converts the new coordinates back to the original measurement system
	//(top to bottom left to right)
	XY new_coordinates; 
	new_coordinates.x= (center.x - a); 
	new_coordinates.y= (center.y - b);
	
	//this is how long the picture is from corner to corner
	//this is needed so that we can resize the new picture to fit the rotation
	//it's passed along as a reference parameter
	diagonal_length= hypotenuse*2+10;

	return new_coordinates;
}


//next function

Rotate::Rotate(string name) {
	image= IMG_Load( name.c_str() );
}


//next function

//this rotates image "degreechange" degrees, writing it the the SDL_Surface "still"
void Rotate::StillFrame(int degreechange) {
	XY currentpoint; currentpoint.x=-1; currentpoint.y=0;

	do{

		//this steps through each pixel, doing the first row, and then dropping down to the next
		if(  ( (currentpoint.x + 1) == image->w)  ) {
			currentpoint.y= (currentpoint.y + 1);
			currentpoint.x= 0;
		}
		else currentpoint.x= (currentpoint.x + 1);


		if(SDL_MUSTLOCK(image)) SDL_LockSurface(image);
		pixel= getpixel(image, currentpoint.x, currentpoint.y);
		if(SDL_MUSTLOCK(image)) SDL_UnlockSurface(image);

		int diagonal_length;
		XY newpoint= CalculateRotation(currentpoint, degreechange, diagonal_length);
		//if this is the first time through, it loads and resizes "still"
		if( (currentpoint.x == 0) && (currentpoint.y == 0) ) {
			still= IMG_Load("blank.png");
			still->w= diagonal_length;
			still->h= diagonal_length;
		}

		//still is bigger than image, so you have to adjust the coordinates
		newpoint.x+= (still->w - image->w)/2;
		newpoint.y+= (still->w - image->w)/2;
		
		if(SDL_MUSTLOCK(still)) SDL_LockSurface(still);
		putpixel(still, newpoint.x, newpoint.y, pixel);
		if(SDL_MUSTLOCK(still)) SDL_UnlockSurface(still);

		//loop until the coordinates reach the end of image
	}while(  !( ( (currentpoint.x + 1) == image->w) && ( (currentpoint.y + 1) == image->h) )  );
}


//next function

void Rotate::Animation(int degreechange) {

}


//main function

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

	Rotate myrotation("imgtest1a.png");
	myrotation.StillFrame(20);

	SDL_Surface *screen= SDL_SetVideoMode(300, 300, 32, SDL_SWSURFACE);

	SDL_Rect offset; offset.x= 25; offset.y= 25;

	SDL_WM_SetCaption("rotate", NULL); //one time it gave me that access error here

	SDL_BlitSurface(myrotation.still, NULL, screen, &offset);

        //and here too, now does that make ANY sense? Oh, and I did check to see
        //if screen was a null pointer, it wasn't. But, just checking caused the error to jump again.
	SDL_Flip(screen);

	SDL_Delay(1000);

	

	return 0;
}


Oh yeah, and one time it crashed but couldn't show me the line in the code, apparently it wasn't there or something. It asked if I want to see the disassembly, and this was what the line where it happened said:
cmp dword ptr [eax+4],edx access violation
Also, it constantly says "<bad ptr>" when I'm watching "p" (it's in the line where it's crashing in the screenshot) Ah,got a screenshot of it here: screenshot 2 Special settings: I am compiling it in release mode to avoid problems surrounding the use of vectors, and, to stop it from giving me crazy values in the watch window during debug (because I'm compiling in release mode), I have it set to no code optimization.

Share this post


Link to post
Share on other sites
Advertisement
Why is symbol "screen" not found? If you try to write to a surface that hasn't been allocated yet, of course you're going to get an error.

Also, are you locking the surface? You need to lock the surface to keep the surface from going away or being modified at the same time you are drawing individual pixels on it.

Share this post


Link to post
Share on other sites
I suspect your rotation code writes to memory outside that allocated to the surface. In this case, it could end up writing anywhere - including over seemingly unrelated variables.

Welcome to C++, here be undefined behaviour [evil]

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
I suspect your rotation code writes to memory outside that allocated to the surface. In this case, it could end up writing anywhere - including over seemingly unrelated variables.

Welcome to C++, here be undefined behaviour [evil]


Thanks for replying! I think I understand what you are saying, but as I said, I'm new to this; could you elaborate?

Share this post


Link to post
Share on other sites
Quote:
Original post by samuraicrow
Why is symbol "screen" not found? If you try to write to a surface that hasn't been allocated yet, of course you're going to get an error.

Also, are you locking the surface? You need to lock the surface to keep the surface from going away or being modified at the same time you are drawing individual pixels on it.


I don't know; I thought it was?

And yes, I am locking the surface.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!