Absent breakpoint triggered while debugging

Started by
5 comments, last by programering 14 years ago
I've encountered a breakpoint problem while debugging my/a SDL application. It breaks in the call of SDL_FreeSurface() in updateSurface() pointed by the green arrow.

bool Sprite::updateSurface()
{
	// WIP:

	if (surface)
		SDL_FreeSurface(surface);   // <-- Here.

	int depth;

	switch (bytesPP)
	{
	case 1:
		depth = 8;
		break;
	case 2:
		depth = 16;
		break;
	case 3:
		depth = 24;
		break;
	case 4:
		depth = 32;
		break;
	default:
		depth = 0;
		break;
	}

	surface = SDL_CreateRGBSurface(0,width,height,depth,0x00ff0000,0x0000ff00,0x000000ff,0x00000000);
	if (!surface)
		return false;

	/* Lock the screen for direct access to the pixels */
    if (SDL_MUSTLOCK(surface))
	{
        if (SDL_LockSurface(surface) < 0)
		{
            SDL_GetError();
            return false;
        }
    }

	Uint8 *pixel = (Uint8 *) surface->pixels;
	Uint32 *write;

	for (Uint32 i = 0; i < pixelCount; i++)
	{
		write = (Uint32 *) pixel;
		*write = pixels[i*bytesPP];
		pixel += bytesPP;
	}

	if (SDL_MUSTLOCK(surface))
		SDL_UnlockSurface(surface);

	return true;
}
test.cpp:

#include "SDL.h"
#include "sprite.h"


Sprite sprite(100,2);
SDL_Surface *screen;
SDL_Event event;
int x, y;


int main(int argc, char *argv[])
{
	SDL_Init(SDL_INIT_VIDEO);

	screen = SDL_SetVideoMode(640,480,32,0);
	SDL_WM_SetCaption("Sprite Test",NULL);

	bool running = true;

	while (running)
	{
		if (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
			case SDL_QUIT:
				running = false;
				break;
			case SDL_MOUSEBUTTONDOWN:
				SDL_GetMouseState(&x,&y);
				sprite.setPixel(x,y,0xffffffff);
				break;
			default:
				break;
			}
		}
		sprite.display(screen,0,0);
		SDL_UpdateRect(screen,0,0,0,0);
	}


	return 0;
}




sprite.h:

#ifndef BASECODE_CPP_SDL_VIDEO_HEADER_SPRITE
#define BASECODE_CPP_SDL_VIDEO_HEADER_SPRITE

#include "SDL_video.h"



class Sprite
{
public:
	// Constructor(s):
	Sprite();
	Sprite(Uint16 size, Uint8 bypp);
	Sprite(Uint16 width, Uint16 height, Uint8 bypp);
	// Initialize:
	void init();
	// Create:
	bool create(Uint16 size, Uint8 bypp);
	bool create(Uint16 width, Uint16 height, Uint8 bypp);
	// Enlarge by x 2:
	bool enlarge();
	// Set:
	bool setPixel(Uint16 x, Uint16 y, Uint32 pix);
	// Display:
	bool display(SDL_Surface *dest, short x, short y);
	// Read from source & write to destination:
	bool readFrom(SDL_Surface *src, SDL_Rect *srcRect);
	bool writeTo(SDL_Surface *dest, SDL_Rect *dstRect);
	bool writeTo(SDL_Surface *dest, SDL_Rect *dstRect, SDL_Rect *srcRect);
	// Get:
	SDL_Surface *getSurface();
	// Destructor:
	~Sprite();
private:
	// Internal members:
	bool alloc();
	void free();
	bool updateSurface();
	
	Uint16 width;
	Uint16 height;
	Uint32 pixelCount;
	Uint8 bytesPP;
	Uint32 pixelsSize;
	Uint8 *pixels;
	SDL_Surface *surface;
	bool success;
};




#endif




sprite.cpp:

#include "sprite.h"



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor(s):

Sprite::Sprite()
{
	init();
}


Sprite::Sprite(Uint16 size, Uint8 bypp)
{
	init();
	success = create(size,bypp);
}


Sprite::Sprite(Uint16 width, Uint16 height, Uint8 bypp)
{
	init();
	success = create(width,height,bypp);
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialize:

void Sprite::init()
{
	pixels = NULL;
	surface = NULL;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create functions:

bool Sprite::create(Uint16 size, Uint8 bypp)
{
	return create(size,size,bypp);
}


bool Sprite::create(Uint16 width, Uint16 height, Uint8 bypp)
{
	this->width = width;
	this->height = height;
	pixelCount = width * height;
	bytesPP = bypp;
	pixelsSize = pixelCount * bytesPP;

	if (!alloc())
		return false;

	updateSurface();
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Update the display surface:

bool Sprite::updateSurface()
{
	// WIP:

	if (surface)
		SDL_FreeSurface(surface);  // <-- Here.

	int depth;

	switch (bytesPP)
	{
	case 1:
		depth = 8;
		break;
	case 2:
		depth = 16;
		break;
	case 3:
		depth = 24;
		break;
	case 4:
		depth = 32;
		break;
	default:
		depth = 0;
		break;
	}

	surface = SDL_CreateRGBSurface(0,width,height,depth,0x00ff0000,0x0000ff00,0x000000ff,0x00000000);
	if (!surface)
		return false;

	/* Lock the screen for direct access to the pixels */
    if (SDL_MUSTLOCK(surface))
	{
        if (SDL_LockSurface(surface) < 0)
		{
            SDL_GetError();
            return false;
        }
    }

	Uint8 *pixel = (Uint8 *) surface->pixels;
	Uint32 *write;

	for (Uint32 i = 0; i < pixelCount; i++)
	{
		write = (Uint32 *) pixel;
		*write = pixels[i*bytesPP];
		pixel += bytesPP;
	}

	if (SDL_MUSTLOCK(surface))
		SDL_UnlockSurface(surface);

	return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Enlarge by x 2:

bool Sprite::enlarge()
{
	// TODO:
	return false;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set:

bool Sprite::setPixel(Uint16 x, Uint16 y, Uint32 pix)
{
	// WIP:
	if (x < width && y < height)
	{
		pixels[y * surface->pitch + x * bytesPP] = pix;
	}
	else
		return false;

	return updateSurface();
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Display:

bool Sprite::display(SDL_Surface *dest, short x, short y)
{
	// TODO:
	if (SDL_BlitSurface(surface,NULL,dest,NULL))
		return false;

	return true;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Read from source & write to destination:
/*
bool Sprite::readFrom(SDL_Surface *src, SDL_Rect *srcRect)
{
	// TODO:
}


bool Sprite::writeTo(SDL_Surface *dest, SDL_Rect *dstRect)
{
	// TODO:
}


bool Sprite::writeTo(SDL_Surface *dest, SDL_Rect *dstRect, SDL_Rect *srcRect)
{
	// TODO:
}
*/

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get:

SDL_Surface *Sprite::getSurface()
{
	return surface;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Free function:

bool Sprite::alloc()
{
	if (pixels)
	{
		// Free first:
		free();
		// Or fail:
	//	return false;
	}

	pixels = new Uint8[pixelsSize];

	if (pixels)
		return true;
	else
		return false;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Free function:

void Sprite::free()
{
	if (pixels)
		delete [] pixels;

	if (surface)
		SDL_FreeSurface(surface);
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Destructor:

Sprite::~Sprite()
{
	free();
}





The output information:

'Sprite.exe': Loaded 'C:\Projects\Programming\Sprite\Debug\Sprite.exe', Symbols loaded.
'Sprite.exe': Loaded 'C:\Windows\System32\ntdll.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\kernel32.dll'
'Sprite.exe': Loaded 'C:\Windows\system\SDL.dll', Binary was not built with debug information.
'Sprite.exe': Loaded 'C:\Windows\System32\advapi32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\rpcrt4.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\gdi32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\user32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\msvcrt.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\winmm.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\ole32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\oleaut32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\oleacc.dll'
'Sprite.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.1_none_bb1f6aa1308c35eb\msvcr90d.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\shimeng.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\apphelp.dll'
'Sprite.exe': Loaded 'C:\Windows\AppPatch\AcLayers.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\shell32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\shlwapi.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\userenv.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\secur32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\winspool.drv'
'Sprite.exe': Loaded 'C:\Windows\System32\mpr.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\imm32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\msctf.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\lpk.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\usp10.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\avgrsstx.dll'
'Sprite.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.18005_none_5cb72f96088b0de0\comctl32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\ddraw.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\dciman32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\setupapi.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\dwmapi.dll'
'Sprite.exe': Unloaded 'C:\Windows\System32\ddraw.dll'
'Sprite.exe': Unloaded 'C:\Windows\System32\dwmapi.dll'
'Sprite.exe': Unloaded 'C:\Windows\System32\setupapi.dll'
'Sprite.exe': Unloaded 'C:\Windows\System32\dciman32.dll'
'Sprite.exe': Loaded 'C:\Windows\System32\KBDUS.DLL'
'Sprite.exe': Unloaded 'C:\Windows\System32\KBDUS.DLL'
'Sprite.exe': Loaded 'C:\Windows\System32\KBDSW.DLL'
'Sprite.exe': Unloaded 'C:\Windows\System32\KBDSW.DLL'
HEAP[Sprite.exe]: Heap block at 00A22F60 modified at 00A27D88 past requested size of 4e20
Windows has triggered a breakpoint in Sprite.exe.

This may be due to a corruption of the heap, which indicates a bug in Sprite.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Sprite.exe has focus.

The output window may have more diagnostic information.
HEAP[Sprite.exe]: Invalid address specified to RtlFreeHeap( 00A20000, 00A22F68 )
Windows has triggered a breakpoint in Sprite.exe.

This may be due to a corruption of the heap, which indicates a bug in Sprite.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Sprite.exe has focus.

The output window may have more diagnostic information.
HEAP[Sprite.exe]: Heap block at 00A29548 modified at 00A2E370 past requested size of 4e20
Windows has triggered a breakpoint in Sprite.exe.

This may be due to a corruption of the heap, which indicates a bug in Sprite.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Sprite.exe has focus.

The output window may have more diagnostic information.
HEAP[Sprite.exe]: Invalid address specified to RtlFreeHeap( 00A20000, 00A29550 )
Windows has triggered a breakpoint in Sprite.exe.

This may be due to a corruption of the heap, which indicates a bug in Sprite.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Sprite.exe has focus.

The output window may have more diagnostic information.
HEAP[Sprite.exe]: Heap block at 02600040 modified at 02604E68 past requested size of 4e20
Windows has triggered a breakpoint in Sprite.exe.

This may be due to a corruption of the heap, which indicates a bug in Sprite.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Sprite.exe has focus.

The output window may have more diagnostic information.


How do I solve this?
Advertisement
Do anyone know how to solve this?
Has it something to do with it's freed in the same function(updateSurface) that it is created in?
See the part that says:
Quote:
HEAP[Sprite.exe]: Heap block at 00A22F60 modified at 00A27D88 past requested size of 4e20


That means you wrote past the end of the allocated memory for the buffer in question. This sort of thing is generally detected when the allocated memory is released, which is happening inside the SDL_FreeSurface call.

Chances you are computing the size of the buffer incorrectly when you're trying to copy data to the surface, or something. Look at your for loop carefully.
HEAP[Sprite.exe]: Heap block at 00A22F60 modified at 00A27D88 past requested size of 4e20HEAP[Sprite.exe]: Invalid address specified to RtlFreeHeap( 00A20000, 00A22F68 )


You have memory corruption.

Start commenting out blocks of code until it starts working.

I didn't take a close look at your code but this jumped out at me:

if (x < width && y < height)	{		pixels[y * surface->pitch + x * bytesPP] = pix;	}


Why are you using surface->pitch? The pitch of pixels[] is not guaranteed to be the same as the pitch of the SDL surface.

Uint8 *pixel = (Uint8 *) surface->pixels;	Uint32 *write;	for (Uint32 i = 0; i < pixelCount; i++)	{		write = (Uint32 *) pixel;		*write = pixels[i*bytesPP];		pixel += bytesPP;	}


Why are you NOT using surface->pitch? The pitch of the SDL surface is not guaranteed to be width*bytesPP.
I was just using the surface->pitch temporarly, and I'll fix this.

The memory write coruption must be here:
*write = pixels[i*bytesPP];

in the middle line of the for loop.
I can't directly see anything wrong with this code:
Uint8 *pixel = (Uint8 *) surface->pixels;Uint32 *write;for (Uint32 i = 0; i < pixelCount; i++){	write = (Uint32 *) pixel;	*write = pixels[i*bytesPP];	pixel += bytesPP;}


... because the 'pixel' is of one byte that gets increased by 'bytesPP' which currently is two. The only thing that I can think of is at the end when the last '*write' assignments or the last ones go out of its scope.

Edit:
Yes when I try to set: if (i < pixelCount-1) before that assignment it don't crashes like that.

// Don't crashes:if (i < pixelCount-1)*write = pixels[i*bytesPP];  . . .if (i < pixelCount) // <-- But this does.*write = pixels[i*bytesPP];


Thanks both for your help. rate+. (Edit2: Had no effect, unfortunatly.)

[Edited by - programering on April 6, 2010 8:59:49 AM]

This topic is closed to new replies.

Advertisement