Data corruption with SDL + Visual C++ 2k8 Optimizations

Started by
1 comment, last by Kylotan 16 years, 3 months ago
I'm getting data corruption on my program when using SDL with Visual C++ 2008 compiler optimizations. For example, issuing the call tr->generatePerlinNoise ( 4, 0.1 ); fails because the generatePerlinNoise method gets a garbage value (e.g 498542) as actual parameter. This does not occur when using no-optimization compilation. Also, argc and argv become garbage as well. I'm using SDL 1.2 built from sources in VC++2008 (no errors). Let's see this code section: int main(int argc, char** argv) { CTerrain * tr = new CTerrain(384); tr->generatePerlinNoise ( 4, 0.1 ); delete tr; return 0; } With no optimizations, correct output code is generated: int main(int argc, char* argv[]) { 00411F70 push ebp 00411F71 mov ebp,esp 00411F73 sub esp,1A0h 00411F79 push ebx 00411F7A push esi 00411F7B push edi 00411F7C lea edi,[ebp-1A0h] 00411F82 mov ecx,68h 00411F87 mov eax,0CCCCCCCCh 00411F8C rep stos dword ptr es:[edi] CGfxcore* gfxc = new CGfxcore(); 00411F8E push 4 00411F90 call operator new (41150Ah) 00411F95 add esp,4 00411F98 mov dword ptr [ebp-18Ch],eax 00411F9E cmp dword ptr [ebp-18Ch],0 00411FA5 je SDL_main+4Ah (411FBAh) 00411FA7 mov ecx,dword ptr [ebp-18Ch] 00411FAD call CGfxcore::CGfxcore (4111F9h) 00411FB2 mov dword ptr [ebp-1A0h],eax 00411FB8 jmp SDL_main+54h (411FC4h) 00411FBA mov dword ptr [ebp-1A0h],0 00411FC4 mov eax,dword ptr [ebp-1A0h] 00411FCA mov dword ptr [ebp-198h],eax 00411FD0 mov ecx,dword ptr [ebp-198h] 00411FD6 mov dword ptr [gfxc],ecx SDL_Event ev; bool running = true; 00411FD9 mov byte ptr [running],1 atexit (SDL_Quit); 00411FDD push offset @ILT+60(_SDL_Quit) (411041h) 00411FE2 call @ILT+490(_atexit) (4111EFh) 00411FE7 add esp,4 if (!(gfxc->initialize(640,480,32))) 00411FEA push 20h 00411FEC push 1E0h 00411FF1 push 280h 00411FF6 mov ecx,dword ptr [gfxc] 00411FF9 call CGfxcore::initialize (41104Bh) 00411FFE movzx eax,al 00412001 test eax,eax 00412003 jne SDL_main+0F1h (412061h) { printf("Error initializing SDL\n"); 00412005 mov esi,esp 00412007 push offset string "Error initializing SDL\n" (41E84Ch) 0041200C call dword ptr [__imp__printf (423584h)] 00412012 add esp,4 00412015 cmp esi,esp 00412017 call @ILT+1075(__RTC_CheckEsp) (411438h) delete gfxc; 0041201C mov eax,dword ptr [gfxc] 0041201F mov dword ptr [ebp-174h],eax 00412025 mov ecx,dword ptr [ebp-174h] 0041202B mov dword ptr [ebp-180h],ecx 00412031 cmp dword ptr [ebp-180h],0 00412038 je SDL_main+0DFh (41204Fh) 0041203A push 1 0041203C mov ecx,dword ptr [ebp-180h] 00412042 call CGfxcore::`scalar deleting destructor' (411366h) 00412047 mov dword ptr [ebp-1A0h],eax 0041204D jmp SDL_main+0E9h (412059h) 0041204F mov dword ptr [ebp-1A0h],0 return -1; 00412059 or eax,0FFFFFFFFh 0041205C jmp SDL_main+2C0h (412230h) } CTerrain * tr = new CTerrain(384); 00412061 push 8 00412063 call operator new (41150Ah) 00412068 add esp,4 0041206B mov dword ptr [ebp-15Ch],eax 00412071 cmp dword ptr [ebp-15Ch],0 00412078 je SDL_main+122h (412092h) 0041207A push 180h 0041207F mov ecx,dword ptr [ebp-15Ch] 00412085 call CTerrain::CTerrain (411172h) 0041208A mov dword ptr [ebp-1A0h],eax 00412090 jmp SDL_main+12Ch (41209Ch) 00412092 mov dword ptr [ebp-1A0h],0 0041209C mov eax,dword ptr [ebp-1A0h] 004120A2 mov dword ptr [ebp-168h],eax 004120A8 mov ecx,dword ptr [ebp-168h] 004120AE mov dword ptr [tr],ecx tr->generatePerlinNoise ( 1, 0.25 ); 004120B1 sub esp,8 004120B4 fld qword ptr [__real@3fd0000000000000 (41E840h)] 004120BA fstp qword ptr [esp] 004120BD push 1 004120BF mov ecx,dword ptr [tr] 004120C2 call CTerrain::generatePerlinNoise (411564h) Now see the mess with optimizations enabled (Optimize for speed): --- c:\documents and settings\hernan\mis documentos\visual studio 2008\projects\sdl1\sdl1\main.cpp 00401002 in al,dx 00401003 and esp,0FFFFFFC0h 00401006 sub esp,30h 00401009 push ebx 0040100A push ebp 0040100B push esi 0040100C push edi CGfxcore* gfxc = new CGfxcore(); 0040100D push 4 0040100F call operator new (4017D4h) 00401014 add esp,4 SDL_Event ev; bool running = true; atexit (SDL_Quit); 00401017 push offset SDL_Quit (401F7Eh) 0040101C mov ebp,eax 0040101E mov byte ptr [esp+27h],1 00401023 call atexit (4017B6h) 00401028 add esp,4 if (!(gfxc->initialize(640,480,32))) 0040102B push 100020h 00401030 call SDL_Init (401F6Ch) 00401035 add esp,4 00401038 test eax,eax 0040103A jne SDL_main+86h (401086h) 0040103C push 40000001h 00401041 push 20h 00401043 push 1E0h 00401048 push 280h 0040104D call SDL_SetVideoMode (401F72h) 00401052 add esp,10h #endif extern "C" int main(int argc, char* argv[]) { CGfxcore* gfxc = new CGfxcore(); SDL_Event ev; bool running = true; atexit (SDL_Quit); if (!(gfxc->initialize(640,480,32))) { printf("Error initializing SDL\n"); delete gfxc; return -1; } CTerrain * tr = new CTerrain(384); 00401055 push 8 00401057 mov dword ptr [ebp],eax 0040105A call operator new (4017D4h) 0040105F mov esi,eax 00401061 xor ebx,ebx 00401063 add esp,4 00401066 cmp esi,ebx 00401068 je SDL_main+0C1h (4010C1h) 0040106A push 24000h 0040106F mov dword ptr [esi+4],180h 00401076 call operator new (4017D4h) 0040107B add esp,4 0040107E mov dword ptr [esi],eax 00401080 mov dword ptr [esp+28h],esi 00401084 jmp SDL_main+0C7h (4010C7h) { printf("Error initializing SDL\n"); 00401086 push 403288h 0040108B call dword ptr [__imp__printf (4030F4h)] 00401091 add esp,4 delete gfxc; 00401094 test ebp,ebp 00401096 je SDL_main+0B6h (4010B6h) 00401098 mov eax,dword ptr [ebp] 0040109B test eax,eax 0040109D je SDL_main+0A8h (4010A8h) 0040109F push eax 004010A0 call SDL_FreeSurface (401F84h) 004010A5 add esp,4 004010A8 call SDL_Quit (401F7Eh) 004010AD push ebp 004010AE call operator delete (4017CEh) 004010B3 add esp,4 return -1; 004010B6 or eax,0FFFFFFFFh while (running) { SDL_PollEvent(&ev); if (ev.type == SDL_KEYDOWN) if (ev.key.keysym.sym == SDLK_ESCAPE ) running = false; //glClear(GL_COLOR_BUFFER_BIT); SDL_Flip(gfxc->getSurface()); //SDL_GL_SwapBuffers(); } delete gfxc; delete tr; return 0; } 004010B9 pop edi 004010BA pop esi 004010BB pop ebp 004010BC pop ebx 004010BD mov esp,ebp 004010BF pop ebp 004010C0 ret } CTerrain * tr = new CTerrain(384); 004010C1 mov dword ptr [esp+28h],ebx 004010C5 mov esi,ebx tr->generatePerlinNoise ( 1, 0.25 ); 004010C7 fld qword ptr [__real@3fd0000000000000 (4032D0h)] 004010CD sub esp,8 004010D0 fstp qword ptr [esp] 004010D3 call CTerrain::generatePerlinNoise (4015B0h) Anyone suffered this problem in this or previous versions of VC++? thanks in advance.
Advertisement
If you're using the debugger to inspect the variables themselves in release code you're going to see garbage values, because the variables are usually not where the debugger expects them to be due to said optimizations. This doesn't mean your code is broken, it just means you can't use this feature of the debugger on release code and expect accurate results.
Ra
Having said that, those values do look broken. The integer parameter doesn't seem to be on the stack and the this pointer isn't being set up at all. The only way that could work is if the generatePerlinNoise has been compiled significantly differently, eg. as a static function rather than a member, and ignoring the first parameter somehow.

(Note to original poster: the code you compiled is not exactly the code you posted at the start - ( 4, 0.1 ) vs ( 1, 0.25 ). )

This topic is closed to new replies.

Advertisement