Sign in to follow this  

Heap Corruption!

This topic is 2002 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'm having trouble locating the cause of a heap corruption I've been getting for last few days. When I debug the corruption doesn't happen in the same place. Visual Studio breaks in a zlib decompression function or in a random fmod call and with Application Verifier, it runs normally, but then breaks in a D3DXSprite call when the player gets to a certain point in the level. I don't even know when this error came up because the debug build never caught it at all. I became aware when someone reported that it wouldn't run on their machine, but it ran fine on mine until I switched to capability mode (I tried all of the options) and I also tried to run it on another machine. I've been trying to solve this for about two weeks now. I tried commenting out portions of code to kind of isolate the problem, but the same thing shows up randomly somewhere else. Any advice will be much appreciated.

Without App Verifier:
[CODE]
int ResourceManager::Uncompress( const unsigned char *src, long srcSize, unsigned char *dst, long destSize)
{
z_stream strm = {0};
strm.total_in = strm.avail_in = srcSize;
strm.total_out = strm.avail_out = destSize;
strm.next_in = (Bytef *) src;
strm.next_out = (Bytef *) dst;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
int err = -1;
int ret = -1;
err = inflateInit2(&strm, (15));
if (err == Z_OK)
{
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END)
{
ret = strm.total_out;
}
else
{
inflateEnd(&strm);
return err;
}
}
else
{
inflateEnd(&strm);
return err;
}
inflateEnd(&strm); //<-------Breaks In This Function. SEE BELOW
return ret;
}
[/CODE]
[CODE]
int ResourceManager::ReadSound( Resource *resource)
{
ResourceSound *res = reinterpret_cast<ResourceSound*>( resource);
FILE *file = NULL;
string fname = WorkingDir + res->Filename;
file = fopen( fname.c_str(), "rb");
if (file == NULL)
{
printf( "Could not read tileset.\n");
res->failed = true;
return -1;
}
long srcSize;
fseek( file, 0, SEEK_END);
srcSize = ftell( file);
fseek( file, 0, SEEK_SET);
unsigned char *srcData = new unsigned char[srcSize];
fread( srcData, 1, srcSize, file);

fclose( file);
long destSize = (srcData[0] << 24) | (srcData[1] << 16) | (srcData[2] << 8) | (srcData[3]);
unsigned char *dest = new unsigned char[destSize];
int uSize = Uncompress( srcData+4, srcSize-4, dest, destSize);//<---------------------- Called Here
if (uSize != destSize)
{
std::string errStr = "For " + res->Name + ", decompressed size of data not equal size written!\n";
printf( errStr.c_str());
res->failed = true;
delete[] srcData;
delete[] dest;
return -1;
}
res->srcId = audioEngine->create_sound_from_data( (char*)dest, destSize, res->Preload);
delete[] srcData;
delete[] dest;
return res->srcId;
}
[/CODE]

Sometimes it breaks in a FMODEX call which I can't debug.

With App Verifier:
[CODE]
int DX9RenderEngine::create_sprite_from_data( const unsigned char* data, UINT size, int FrameCount, int FrameWidth, int FrameHeight, float CenterX, float CenterY, Color colkey, bool preload)
{
Sprite *spr = new Sprite;
spr->preload = preload;
D3DXIMAGE_INFO info;
D3DXGetImageInfoFromFileInMemory( data, size, &info); //<------- Breaks in this function
spr->fname = "";
spr->ImageWidth = info.Width;
spr->ImageHeight = info.Height;
spr->FrameCount = FrameCount;
spr->FrameWidth = FrameWidth == -1 ? info.Width : FrameWidth;
spr->FrameHeight = FrameHeight == -1 ? info.Height : FrameHeight;
spr->CenterX = CenterX;
spr->CenterY = CenterY;
spr->ColorKey = colkey;
spr->fromData = true;
spr->data = new unsigned char[size];
memcpy( spr->data, data, size);
spr->dataSize = size;
if (preload)
{
InitializeSprite( spr);
}
return append_sprite( spr);
}
[/CODE]

if not there it eventually breaks on D3DXSprite::End(); Edited by justin12343

Share this post


Link to post
Share on other sites
[quote name='justin12343' timestamp='1339994168' post='4950140']
[code]
long destSize = (srcData[0] << 24) | (srcData[1] << 16) | (srcData[2] << 8) | (srcData[3]);
[/code]
[/quote]

Is your machine big-endian? Most machines are little-endian, meaning 0xDEADBEEF is stored as 0xEF 0xBE 0xAD 0xDE. It's quite possible that you have a destination size that is actually larger than what you are interpreting, therefore stomping a good chunk of memory. (For example, a the size of a 65536-byte file is written to the file as 0x00010000, but is interpreted as 0x00000100 when read with the code above.)

Possible solution:
[code]
long destSize = ((long*)srcData)[0];
[/code]

It is also possible the seemingly unrelated errors stem from this problem as well. Edited by fastcall22

Share this post


Link to post
Share on other sites
For D3D9 endianness is [i]highly[/i] unlikely to be a factor. My money's on an uninitialized pointer or bad pointer being passed to a function. Random breaks/etc would match that behaviour.

Share this post


Link to post
Share on other sites
Run your program through a memory analysis tool. It'll tell you what you are doing wrong (most likely!). If you can compile on *nix, try valgrind. Otherwise, maybe Dr. Memory could help you (on Windows). I maintain a linux build just because of the great tooling support for C++ dev.

Share this post


Link to post
Share on other sites
[quote name='CyberRascal' timestamp='1340019170' post='4950209']
Run your program through a memory analysis tool. It'll tell you what you are doing wrong (most likely!). If you can compile on *nix, try valgrind. Otherwise, maybe Dr. Memory could help you (on Windows). I maintain a linux build just because of the great tooling support for C++ dev.
[/quote]
The program is clearly D3D9.

Share this post


Link to post
Share on other sites
[quote name='mhagain' timestamp='1340020056' post='4950213']
The program is clearly D3D9.
[/quote]

Quite obviously it is, indeed. Sorry bout that. Rest of the post should apply though.

Share this post


Link to post
Share on other sites
Uninitialized reads means that you read something without zeroing or assigning it - in other words, you are probably reading scrap memory. It is memory that is allocated (so no segfault or exception) but if you take actions based on that value, it could possibly do different things depending on mostly compiler versions. (if the compiler version changes the layout of the memory somehow you will read other scrap memory).

Unaddressable accesses are a big no-no. It means that you are reading or writing to invalid locations (which could kill your heap, or stack, for example). You've got

110 unique, 1294243 total unaddressable access(es).

The sad thing is that it's not trivially easy to know which errors are your own fault, and which errors are library errors that shouldn't be reported. But invalid accesses are invalid accesses, and shouldn't occur at all.

Invalid heap argument means that you are trying to delete an invalid area - either an invalid address, an already deleted pointer, or probably also (hupsilardee's question) non-dynamically allocated pointer deletion.

The Dr Memory output seems to suggest that your application is either explicitly trampling memory (i.e your fault) or implicitly (i.e a library that you have no control over)

Focus on unaddressable accesses and invalid heap arguments. Try running your program for a shorter time to get less non-unique output, or if Dr Memory supports it only report unique errors.

Cheers. Edited by CyberRascal

Share this post


Link to post
Share on other sites
How do you call ResourceManager::ReadSound(Resource*) ?

I'm [i]very curious[/i] why you [b]printf("could not read tileset")[/b] inside a method that's called [b]ReadSound[/b]...

Share this post


Link to post
Share on other sites
[quote name='alnite' timestamp='1340132371' post='4950672']
How do you call ResourceManager::ReadSound(Resource*) ?

I'm [i]very curious[/i] why you [b]printf("could not read tileset")[/b] inside a method that's called [b]ReadSound[/b]...
[/quote]
That was a simple copy/paste error. ReadTileset looks almost the same as ReadSound so I just copied and pasted and changed the way the data was used.

I think I'm getting closer to the problem. I noticed that new Sprite was being called twice in the create_sprite_from_data function though a call to new is only there once, But in the disassembly its clearly there twice. The first time it is called every thing seems fine except it doesn't go through the rest of the function. The second time, the whole renderer class goes invalid before and then new is called. I'll post the disassembly so you guys can see.

[CODE]
int DX9RenderEngine::create_sprite_from_data( const unsigned char* data, UINT size, int FrameCount, int FrameWidth, int FrameHeight, float CenterX, float CenterY, Color colkey, bool preload)
{
013FF680 push ebp
013FF681 mov ebp,esp
013FF683 sub esp,28h
013FF686 mov eax,dword ptr [___security_cookie (16774E8h)]
013FF68B xor eax,ebp
013FF68D mov dword ptr [ebp-4],eax
013FF690 mov eax,dword ptr [ebp+8]
013FF693 push ebx
013FF694 push esi
013FF695 push edi
013FF696 mov edi,dword ptr [ebp+0Ch]
Sprite *spr = new Sprite;
013FF699 push 60h
013FF69B mov dword ptr [ebp-24h],ecx
spr->FrameHeight = FrameHeight == -1 ? info.Height : FrameHeight;
013FF69E mov dword ptr [ebp-28h],eax
013FF6A1 call operator new (15686AEh)
013FF6A6 xor ebx,ebx
013FF6A8 add esp,4
013FF6AB cmp eax,ebx
013FF6AD je DX9RenderEngine::create_sprite_from_data+78h (13FF6F8h)
Sprite *spr = new Sprite;
013FF6AF fldz
013FF6B1 mov dword ptr [eax],offset Sprite::`vftable' (15F73D4h)
013FF6B7 mov dword ptr [eax+18h],0Fh
013FF6BE mov dword ptr [eax+14h],ebx
013FF6C1 mov byte ptr [eax+4],bl
013FF6C4 fst dword ptr [eax+40h]
013FF6C7 fstp dword ptr [eax+44h]
013FF6CA mov byte ptr [eax+20h],bl
013FF6CD mov dword ptr [eax+24h],ebx
013FF6D0 mov dword ptr [eax+28h],ebx
013FF6D3 mov dword ptr [eax+2Ch],ebx
013FF6D6 mov dword ptr [eax+30h],ebx
013FF6D9 mov dword ptr [eax+34h],ebx
013FF6DC mov dword ptr [eax+38h],ebx
013FF6DF mov dword ptr [eax+3Ch],ebx
013FF6E2 mov dword ptr [eax+48h],ebx
013FF6E5 mov byte ptr [eax+4Ch],bl
013FF6E8 mov dword ptr [eax+50h],ebx
013FF6EB mov dword ptr [eax+54h],ebx
013FF6EE mov dword ptr [eax+58h],ebx
013FF6F1 mov byte ptr [eax+4Dh],bl
013FF6F4 mov esi,eax
013FF6F6 jmp DX9RenderEngine::create_sprite_from_data+7Ah (13FF6FAh)
013FF6F8 xor esi,esi
D3DXIMAGE_INFO info;
D3DXGetImageInfoFromFileInMemory( data, size, &info);
013FF6FA mov edx,dword ptr [ebp-28h]
013FF6FD lea ecx,[ebp-20h]
013FF700 push ecx
013FF701 push edi
013FF702 push edx
013FF703 call D3DXGetImageInfoFromFileInMemory (15566A4h)
spr->fname = "";
013FF708 push ebx
013FF709 push offset string "" (1631574h)
013FF70E lea ecx,[esi+4]
013FF711 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign (13C0210h)
spr->ImageWidth = info.Width;
013FF716 mov eax,dword ptr [ebp-20h]
spr->ImageHeight = info.Height;
spr->FrameCount = FrameCount;
013FF719 mov edx,dword ptr [ebp+10h]
013FF71C mov dword ptr [esi+2Ch],eax
013FF71F mov ecx,dword ptr [ebp-1Ch]
spr->FrameWidth = FrameWidth == -1 ? info.Width : FrameWidth;
013FF722 mov eax,dword ptr [ebp+14h]
013FF725 mov dword ptr [esi+30h],ecx
013FF728 mov dword ptr [esi+34h],edx
013FF72B cmp eax,0FFFFFFFFh
013FF72E jne DX9RenderEngine::create_sprite_from_data+0B3h (13FF733h)
013FF730 mov eax,dword ptr [ebp-20h]
013FF733 mov dword ptr [esi+38h],eax
spr->FrameHeight = FrameHeight == -1 ? info.Height : FrameHeight;
013FF736 mov eax,dword ptr [ebp+18h]
013FF739 cmp eax,0FFFFFFFFh
013FF73C jne DX9RenderEngine::create_sprite_from_data+0C1h (13FF741h)
013FF73E mov eax,dword ptr [ebp-1Ch]
spr->CenterX = CenterX;
013FF741 fld dword ptr [ebp+1Ch]
spr->CenterY = CenterY;
spr->ColorKey = colkey;
spr->preload = preload;
013FF744 mov cl,byte ptr [ebp+28h]
013FF747 fstp dword ptr [esi+40h]
013FF74A mov dword ptr [esi+3Ch],eax
013FF74D mov eax,dword ptr [ebp+24h]
013FF750 fld dword ptr [ebp+20h]
spr->fromData = true;
spr->data = new unsigned char[size];
013FF753 push edi
013FF754 fstp dword ptr [esi+44h]
013FF757 mov dword ptr [esi+48h],eax
013FF75A mov byte ptr [esi+4Ch],cl
013FF75D mov byte ptr [esi+20h],1
013FF761 call operator new[] (1568308h)
memcpy( spr->data, data, size);
013FF766 mov edx,dword ptr [ebp-28h]
013FF769 push edi
013FF76A push edx
013FF76B push eax
013FF76C mov dword ptr [esi+28h],eax
013FF76F call memcpy (1568696h)
013FF774 add esp,10h
spr->dataSize = size;
013FF777 mov dword ptr [esi+24h],edi
if (preload)
{
InitializeSprite( spr);
013FF77A mov edi,dword ptr [ebp-24h]
013FF77D cmp byte ptr [ebp+28h],bl
013FF780 je DX9RenderEngine::create_sprite_from_data+10Fh (13FF78Fh)
013FF782 mov eax,dword ptr [edi]
013FF784 mov edx,dword ptr [eax+88h]
013FF78A push esi
013FF78B mov ecx,edi
013FF78D call edx
}
return append_sprite( spr);
013FF78F push esi
013FF790 mov ecx,edi
013FF792 call Renderer::append_sprite (142DF30h)
}
[/CODE]

Share this post


Link to post
Share on other sites
[quote name='justin12343' timestamp='1340154719' post='4950791']
That was a simple copy/paste error. ReadTileset looks almost the same as ReadSound so I just copied and pasted and changed the way the data was used.
[/quote]
Ok, but how and where do you call that method? I have a suspicion that's where the problem is.

Share this post


Link to post
Share on other sites
[quote name='alnite' timestamp='1340223838' post='4951110']
[quote name='justin12343' timestamp='1340154719' post='4950791']
That was a simple copy/paste error. ReadTileset looks almost the same as ReadSound so I just copied and pasted and changed the way the data was used.
[/quote]
Ok, but how and where do you call that method? I have a suspicion that's where the problem is.
[/quote]

[CODE]
int ResourceManager::ReadTileset( Resource *resource)
{
ResourceTileset *res = reinterpret_cast<ResourceTileset*>( resource);
FILE *file = NULL;
std::string fname = WorkingDir + res->Filename;
file = fopen( fname.c_str(), "rb");
if (file == NULL)
{
printf( "Could not read tileset.\n");
return -1;
}
long srcSize;
fseek( file, 0, SEEK_END);
srcSize = ftell( file);
fseek( file, 0, SEEK_SET);
unsigned char *srcData = new unsigned char[srcSize];
fread( srcData, 1, srcSize, file);

fclose( file);
long destSize = (srcData[0] << 24) | (srcData[1] << 16) | (srcData[2] << 8) | (srcData[3]);
unsigned char *dest = new unsigned char[destSize];
int uSize = Uncompress( srcData+4, srcSize-4, dest, destSize);
if (uSize != destSize)
{
std::string errStr = "For " + res->Name + ", decompressed size of data not equal size written!\n";
printf( errStr.c_str());
res->failed = true;
delete[] srcData;
delete[] dest;
return -1;
}
int index = renderEngine->create_tileset_from_data( dest, destSize, res->TileWidth, res->TileHeight, res->XOffset, res->YOffset, res->XSpacing, res->YSpacing);

delete[] srcData;
delete[] dest;
if (index == -1)
{
printf( "Error loading tileset.\n");
res->failed = true;
return -1;
}
res->srcId = index;
res->loaded = true;
return index;
}
[/CODE]

Share this post


Link to post
Share on other sites

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