c++ - Optimizer bug (allocation of local variables on the stack)
-
Christof Meerwald
(48/48)
Apr 05 2003
#include
- Heinz Saathoff (13/55) Apr 07 2003 ^^^^^^^^^^^^^^^^^
- Walter (5/5) Apr 07 2003 Christof's reported bug was corrected in the latest beta. The code looks...
- Heinz Saathoff (30/35) Apr 08 2003 To check if I get the stack overflow exception I tried this code:
- Walter (7/42) Apr 08 2003 That's because a certain amount of stack is preallocated. I don't know h...
- mjs NOSPAM.hannover.sgh-net.de (Mark Junker) (3/5) Apr 10 2003 Isn't that defined by the linker-produced PE file?
- Walter (4/9) Apr 10 2003 Probably; I'd have to read the spec again.
#include <stdio.h> void f(); int main() { f(); } void f() { int i1 = 1234, i2 = 5678; char c[8*4096]; printf("%08x %08x %08x\n", &c, &i1, &i2); } Compiled with (-o+speed) I get: 4067ae54 000004d2 0000162e Obviously, 0x4d2 and 0x162e aren't the addresses of i1 and i2 (but the values), so let's have a look at the generated code: ?f YAXXZ: push EBP mov EBP,ESP mov EDX,8 ; allocation of 8*4096 bytes on the stack L18: sub ESP,01000h test [ESP],ESP dec EDX jne L18 ; and here the compiler assumes that EDX is still 8 (but it is 0 now) ; this doesn't allocate any space on the stack sub ESP,EDX lea EAX,-08004h[EBP] lea ECX,-08008h[EBP] push EAX lea EDX,-08000h[EBP] push ECX push EDX ; finally overwrites the passed arguments to printf mov dword ptr -08008h[EBP],04D2h mov dword ptr -08004h[EBP],0162Eh push offset FLAT:_DATA call near ptr _printf add ESP,010h mov ESP,EBP pop EBP ret bye, Christof -- http://cmeerw.org JID: cmeerw jabber.at mailto cmeerw at web.de ...and what have you contributed to the Net?
Apr 05 2003
Hello Christof, Hello Walter, Christof Meerwald schrieb...[snip] void f() { int i1 = 1234, i2 = 5678; char c[8*4096]; printf("%08x %08x %08x\n", &c, &i1, &i2); } Compiled with (-o+speed) I get: 4067ae54 000004d2 0000162e Obviously, 0x4d2 and 0x162e aren't the addresses of i1 and i2 (but the values), so let's have a look at the generated code: ?f YAXXZ: push EBP mov EBP,ESP mov EDX,8 ; allocation of 8*4096 bytes on the stack L18: sub ESP,01000h test [ESP],ESP^^^^^^^^^^^^^^^^^ why test ESP with [ESP]? Doesn't make much sense to me except to force a protection fault in case of stack overflowdec EDX jne L18Why allocate the 8*4096 in a loop and not direct? If a early stack protection fault should be forced the allocation could be done as sub ESP,08000h ; allocate at once test [ESP],ESP ; early protection fault when ; stack overflows; and here the compiler assumes that EDX is still 8 (but it is 0 now) ; this doesn't allocate any space on the stack sub ESP,EDX lea EAX,-08004h[EBP] lea ECX,-08008h[EBP] push EAX lea EDX,-08000h[EBP] push ECX push EDX ; finally overwrites the passed arguments to printf mov dword ptr -08008h[EBP],04D2hBTW, the space allocation on the stack for i1 and i2 is also missing. ESP should be subtracted by 08008h instead of only 08000h. - Heinz
Apr 07 2003
Christof's reported bug was corrected in the latest beta. The code looks a little wierd, but it works because the stack cannot be extended by more than 4k at a time (or else you get a stack overflow exception). Thus, it does it 4k at a time, doing a read from each 4k block to get win32 to allocate another page to the stack.
Apr 07 2003
Walter schrieb...Christof's reported bug was corrected in the latest beta. The code looks a little wierd, but it works because the stack cannot be extended by more than 4k at a time (or else you get a stack overflow exception). Thus, it does it 4k at a time, doing a read from each 4k block to get win32 to allocate another page to the stack.To check if I get the stack overflow exception I tried this code: /*------------- ST.C --------------*/ #include <stdio.h> void Func() { asm { push EBP mov EBP,ESP sub ESP,0100000h /* 1M on stack */ mov EBX,ESP mov ECX,0100000h/4 LL: mov dword ptr [EBX],0 add EBX,4 loop LL mov ESP,EBP pop EBP } }//Func int main() { printf("call Func\n"); Func(); printf("ready\n"); return 0; } /*------------ end ST.C -----------*/ Compiled with sc -nm st.c and run on NT4 I didn't get any exception. - Heinz
Apr 08 2003
That's because a certain amount of stack is preallocated. I don't know how much it is, I'm sure that it changes from version to version of win32. "Heinz Saathoff" <hsaat bre.ipnet.de> wrote in message news:MPG.18fc9d4b387f5b289896b8 news.digitalmars.com...Walter schrieb...aChristof's reported bug was corrected in the latest beta. The code looksthanlittle wierd, but it works because the stack cannot be extended by moreit4k at a time (or else you get a stack overflow exception). Thus, it does4k at a time, doing a read from each 4k block to get win32 to allocate another page to the stack.To check if I get the stack overflow exception I tried this code: /*------------- ST.C --------------*/ #include <stdio.h> void Func() { asm { push EBP mov EBP,ESP sub ESP,0100000h /* 1M on stack */ mov EBX,ESP mov ECX,0100000h/4 LL: mov dword ptr [EBX],0 add EBX,4 loop LL mov ESP,EBP pop EBP } }//Func int main() { printf("call Func\n"); Func(); printf("ready\n"); return 0; } /*------------ end ST.C -----------*/ Compiled with sc -nm st.c and run on NT4 I didn't get any exception. - Heinz
Apr 08 2003
That's because a certain amount of stack is preallocated. I don't know how much it is, I'm sure that it changes from version to version of win32.Isn't that defined by the linker-produced PE file? Regards, MJS
Apr 10 2003
Probably; I'd have to read the spec again. "Mark Junker" <mjs NOSPAM.hannover.sgh-net.de> wrote in message news:8j$7UuRd8gB hannover.sgh-net.de...howThat's because a certain amount of stack is preallocated. I don't knowmuch it is, I'm sure that it changes from version to version of win32.Isn't that defined by the linker-produced PE file? Regards, MJS
Apr 10 2003