www.digitalmars.com         C & C++   DMDScript  

c++ - Optimizer bug (allocation of local variables on the stack)

reply Christof Meerwald <cmeerw web.de> writes:
#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
next sibling parent reply Heinz Saathoff <hsaat bre.ipnet.de> writes:
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 overflow
 		dec	EDX
 		jne	L18

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],04D2h

BTW, 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
parent reply "Walter" <walter digitalmars.com> writes:
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
parent reply Heinz Saathoff <hsaat bre.ipnet.de> writes:
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
parent "Walter" <walter digitalmars.com> writes:
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...
 Christof's reported bug was corrected in the latest beta. The code looks


 little wierd, but it works because the stack cannot be extended by more


 4k at a time (or else you get a stack overflow exception). Thus, it does


 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
prev sibling parent reply mjs NOSPAM.hannover.sgh-net.de (Mark Junker) writes:
 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.

Regards, MJS
Apr 10 2003
parent "Walter" <walter digitalmars.com> writes:
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...
 That's because a certain amount of stack is preallocated. I don't know


 much it is, I'm sure that it changes from version to version of win32.

Regards, MJS

Apr 10 2003