Visual C++ optimizer bug (reported by a friend in the Computer Chess Club)

G

Guest

When optimization is turned on (these settings will reproduce it along with others):
/Ox /Og /Ob2 /Oi /Ot /Oy /GT /GL /G6 /GA /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /ML /Gy /Fp".\Release/bug.pch" /FAcs /Fa".\Release/" /Fo".\Release/" /Fd".\Release/" /W4 /nologo /c /TP

This program crashes heinously:

#include <stdio.h>
#include <stdlib.h>
unsigned int a[144];

void init ()
{
unsigned int i;
for (i = 0; i < 144; i++)
a = rand();
}

void dump ()
{
unsigned int row, col;
for (row = 11; row < 12; row--) // <--- PROBLEM: row < 12
{
for (col = 0; col < 12; col++)
printf("%u ", a[(row * 12) + col]);
putchar('\n');
}
}

int main ()
{
init();
dump();
return 0;
}

Here is the resultant assembly language:

; Listing generated by Microsoft (R) Optimizing Compiler Version 13.10.3077

TITLE .\bug.cpp
.386P
include listing.inc
if @version gt 510
..model FLAT
else
; COMDAT ??_C@_03IOOJPBPG@?$CFu?5?$AA@
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
; COMDAT ?init@@YAXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ?dump@@YAXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT _main
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif

INCLUDELIB LIBC
INCLUDELIB OLDNAMES

PUBLIC ??_C@_03IOOJPBPG@?$CFu?5?$AA@ ; `string'
PUBLIC ?a@@3PAIA ; a
EXTRN __iob:BYTE
EXTRN __flsbuf:NEAR
EXTRN _rand:NEAR
EXTRN _printf:NEAR
?a@@3PAIA DD 090H DUP (?) ; a
; COMDAT ??_C@_03IOOJPBPG@?$CFu?5?$AA@
CONST SEGMENT
??_C@_03IOOJPBPG@?$CFu?5?$AA@ DB '%u ', 00H ; `string'
CONST ENDS
PUBLIC ?dump@@YAXXZ ; dump
; Function compile flags: /Ogty
; File c:\tmp\bug.cpp
; COMDAT ?dump@@YAXXZ
_TEXT SEGMENT
?dump@@YAXXZ PROC NEAR ; dump, COMDAT

; 13 : {

00000 53 push ebx
00001 56 push esi
00002 57 push edi

; 14 : unsigned int row, col;
; 15 : for (row = 11; row < 12; row--) // <--- PROBLEM: row < 12

00003 bb 10 02 00 00 mov ebx, OFFSET FLAT:?a@@3PAIA+528
00008 eb 06 8d 9b 00
00 00 00 npad 8
$L980:

; 16 : {
; 17 : for (col = 0; col < 12; col++)

00010 8b f3 mov esi, ebx
00012 bf 0c 00 00 00 mov edi, 12 ; 0000000cH
$L983:

; 18 : printf("%u ", a[(row * 12) + col]);

00017 8b 06 mov eax, DWORD PTR [esi]
00019 50 push eax
0001a 68 00 00 00 00 push OFFSET FLAT:??_C@_03IOOJPBPG@?$CFu?5?$AA@
0001f e8 00 00 00 00 call _printf
00024 83 c4 08 add esp, 8
00027 83 c6 04 add esi, 4
0002a 4f dec edi
0002b 75 ea jne SHORT $L983

; 19 : putchar('\n');

0002d ff 0d 24 00 00
00 dec DWORD PTR __iob+36
00033 78 11 js SHORT $L1000
00035 8b 0d 20 00 00
00 mov ecx, DWORD PTR __iob+32
0003b c6 01 0a mov BYTE PTR [ecx], 10 ; 0000000aH
0003e ff 05 20 00 00
00 inc DWORD PTR __iob+32
00044 eb 0f jmp SHORT $L981
$L1000:
00046 68 20 00 00 00 push OFFSET FLAT:__iob+32
0004b 6a 0a push 10 ; 0000000aH
0004d e8 00 00 00 00 call __flsbuf
00052 83 c4 08 add esp, 8
$L981:
00055 83 eb 30 sub ebx, 48 ; 00000030H
00058 81 fb 40 02 00
00 cmp ebx, OFFSET FLAT:?a@@3PAIA+576
0005e 72 b0 jb SHORT $L980
00060 5f pop edi
00061 5e pop esi
00062 5b pop ebx

; 20 : }
; 21 : }

00063 c3 ret 0
?dump@@YAXXZ ENDP ; dump
_TEXT ENDS
PUBLIC ?init@@YAXXZ ; init
; Function compile flags: /Ogty
; COMDAT ?init@@YAXXZ
_TEXT SEGMENT
?init@@YAXXZ PROC NEAR ; init, COMDAT

; 6 : {

00000 56 push esi

; 7 : unsigned int i;
; 8 : for (i = 0; i < 144; i++)

00001 33 f6 xor esi, esi
$L973:

; 9 : a = rand();

00003 e8 00 00 00 00 call _rand
00008 89 86 00 00 00
00 mov DWORD PTR ?a@@3PAIA[esi], eax
0000e 83 c6 04 add esi, 4
00011 81 fe 40 02 00
00 cmp esi, 576 ; 00000240H
00017 72 ea jb SHORT $L973
00019 5e pop esi

; 10 : }

0001a c3 ret 0
?init@@YAXXZ ENDP ; init
_TEXT ENDS
PUBLIC _main
; Function compile flags: /Ogty
; COMDAT _main
_TEXT SEGMENT
_main PROC NEAR ; COMDAT

; 24 : {

00000 56 push esi

; 25 : init();

00001 33 f6 xor esi, esi
$L1017:
00003 e8 00 00 00 00 call _rand
00008 89 86 00 00 00
00 mov DWORD PTR ?a@@3PAIA[esi], eax
0000e 83 c6 04 add esi, 4
00011 81 fe 40 02 00
00 cmp esi, 576 ; 00000240H
00017 72 ea jb SHORT $L1017

; 26 : dump();

00019 e8 00 00 00 00 call ?dump@@YAXXZ ; dump

; 27 : return 0;

0001e 33 c0 xor eax, eax
00020 5e pop esi

; 28 : }

00021 c3 ret 0
_main ENDP
_TEXT ENDS
END
 
C

Carl Daniel [VC++ MVP]

Truly awful code, but AFICT leagal according to the C++ standard. Sure
looks like a bug to me too. I'll make sure MS knows about it if it's not
already fixed in Whidbey.
-cd

Dann said:
When optimization is turned on (these settings will reproduce it
along with others): /Ox /Og /Ob2 /Oi /Ot /Oy /GT /GL /G6 /GA /D
"WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /ML /Gy
/Fp".\Release/bug.pch" /FAcs /Fa".\Release/" /Fo".\Release/"
/Fd".\Release/" /W4 /nologo /c /TP

This program crashes heinously:

#include <stdio.h>
#include <stdlib.h>
unsigned int a[144];

void init ()
{
unsigned int i;
for (i = 0; i < 144; i++)
a = rand();
}

void dump ()
{
unsigned int row, col;
for (row = 11; row < 12; row--) // <--- PROBLEM: row < 12
{
for (col = 0; col < 12; col++)
printf("%u ", a[(row * 12) + col]);
putchar('\n');
}
}

int main ()
{
init();
dump();
return 0;
}

Here is the resultant assembly language:

; Listing generated by Microsoft (R) Optimizing Compiler Version
13.10.3077

TITLE .\bug.cpp
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
; COMDAT ??_C@_03IOOJPBPG@?$CFu?5?$AA@
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
; COMDAT ?init@@YAXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ?dump@@YAXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT _main
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif

INCLUDELIB LIBC
INCLUDELIB OLDNAMES

PUBLIC ??_C@_03IOOJPBPG@?$CFu?5?$AA@ ; `string'
PUBLIC ?a@@3PAIA ; a
EXTRN __iob:BYTE
EXTRN __flsbuf:NEAR
EXTRN _rand:NEAR
EXTRN _printf:NEAR
?a@@3PAIA DD 090H DUP (?) ; a
; COMDAT ??_C@_03IOOJPBPG@?$CFu?5?$AA@
CONST SEGMENT
??_C@_03IOOJPBPG@?$CFu?5?$AA@ DB '%u ', 00H ; `string'
CONST ENDS
PUBLIC ?dump@@YAXXZ ; dump
; Function compile flags: /Ogty
; File c:\tmp\bug.cpp
; COMDAT ?dump@@YAXXZ
_TEXT SEGMENT
?dump@@YAXXZ PROC NEAR ; dump, COMDAT

; 13 : {

00000 53 push ebx
00001 56 push esi
00002 57 push edi

; 14 : unsigned int row, col;
; 15 : for (row = 11; row < 12; row--) // <--- PROBLEM: row
< 12

00003 bb 10 02 00 00 mov ebx, OFFSET FLAT:?a@@3PAIA+528
00008 eb 06 8d 9b 00
00 00 00 npad 8
$L980:

; 16 : {
; 17 : for (col = 0; col < 12; col++)

00010 8b f3 mov esi, ebx
00012 bf 0c 00 00 00 mov edi, 12 ; 0000000cH
$L983:

; 18 : printf("%u ", a[(row * 12) + col]);

00017 8b 06 mov eax, DWORD PTR [esi]
00019 50 push eax
0001a 68 00 00 00 00 push OFFSET FLAT:??_C@_03IOOJPBPG@?$CFu?5?$AA@
0001f e8 00 00 00 00 call _printf
00024 83 c4 08 add esp, 8
00027 83 c6 04 add esi, 4
0002a 4f dec edi
0002b 75 ea jne SHORT $L983

; 19 : putchar('\n');

0002d ff 0d 24 00 00
00 dec DWORD PTR __iob+36
00033 78 11 js SHORT $L1000
00035 8b 0d 20 00 00
00 mov ecx, DWORD PTR __iob+32
0003b c6 01 0a mov BYTE PTR [ecx], 10 ; 0000000aH
0003e ff 05 20 00 00
00 inc DWORD PTR __iob+32
00044 eb 0f jmp SHORT $L981
$L1000:
00046 68 20 00 00 00 push OFFSET FLAT:__iob+32
0004b 6a 0a push 10 ; 0000000aH
0004d e8 00 00 00 00 call __flsbuf
00052 83 c4 08 add esp, 8
$L981:
00055 83 eb 30 sub ebx, 48 ; 00000030H
00058 81 fb 40 02 00
00 cmp ebx, OFFSET FLAT:?a@@3PAIA+576
0005e 72 b0 jb SHORT $L980
00060 5f pop edi
00061 5e pop esi
00062 5b pop ebx

; 20 : }
; 21 : }

00063 c3 ret 0
?dump@@YAXXZ ENDP ; dump
_TEXT ENDS
PUBLIC ?init@@YAXXZ ; init
; Function compile flags: /Ogty
; COMDAT ?init@@YAXXZ
_TEXT SEGMENT
?init@@YAXXZ PROC NEAR ; init, COMDAT

; 6 : {

00000 56 push esi

; 7 : unsigned int i;
; 8 : for (i = 0; i < 144; i++)

00001 33 f6 xor esi, esi
$L973:

; 9 : a = rand();

00003 e8 00 00 00 00 call _rand
00008 89 86 00 00 00
00 mov DWORD PTR ?a@@3PAIA[esi], eax
0000e 83 c6 04 add esi, 4
00011 81 fe 40 02 00
00 cmp esi, 576 ; 00000240H
00017 72 ea jb SHORT $L973
00019 5e pop esi

; 10 : }

0001a c3 ret 0
?init@@YAXXZ ENDP ; init
_TEXT ENDS
PUBLIC _main
; Function compile flags: /Ogty
; COMDAT _main
_TEXT SEGMENT
_main PROC NEAR ; COMDAT

; 24 : {

00000 56 push esi

; 25 : init();

00001 33 f6 xor esi, esi
$L1017:
00003 e8 00 00 00 00 call _rand
00008 89 86 00 00 00
00 mov DWORD PTR ?a@@3PAIA[esi], eax
0000e 83 c6 04 add esi, 4
00011 81 fe 40 02 00
00 cmp esi, 576 ; 00000240H
00017 72 ea jb SHORT $L1017

; 26 : dump();

00019 e8 00 00 00 00 call ?dump@@YAXXZ ; dump

; 27 : return 0;

0001e 33 c0 xor eax, eax
00020 5e pop esi

; 28 : }

00021 c3 ret 0
_main ENDP
_TEXT ENDS
END
 
C

Carl Daniel [VC++ MVP]

Carl said:
Truly awful code, but AFICT leagal according to the C++ standard.
Sure looks like a bug to me too. I'll make sure MS knows about it if
it's not already fixed in Whidbey.

This is fixed in Whidbey.

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top