Author: Dann Corbit
Date: 15:24:04 04/09/04
Go up one level in this thread
On April 09, 2004 at 18:04:10, Russell Reagan wrote:
>I'm posting this here because I know that some of the programmers here use MSVC
>.NET 2003, and in hopes that Eugene will read this :)
>
>Today I had a problem with a program I was writing, and I came across what I
>believe is an optimization bug. I wrote this little program to reproduce the
>bug. If I compile with optimizations set to "Disabled", there is no problem. If
>I compile with optimzations set to anything else (Maximize Speed, Minimize Size,
>Full Optimizations), the program crashes due to a loop never terminating. The
>source code is at the end of this message. The line where the problem occurs is:
>
>for (row = 11; row < 12; row--)
>
>The problem is the comparison: row < 12
>
>When optimizations are turned off, this is the assembly output for that
>comparison:
>
>cmp DWORD PTR _row$[ebp], 12
>
>If optimizations are turned on, this is the assembly output:
>
>cmp ebx, OFFSET FLAT:_a+576
>
>I'm no assembly expert, but that looks like it is comparing the address of two
>pointers to me, and has nothing to do with comparing two values.
>
>Here is the example C source code. I compiled it under GCC with and without
>optimizations and it ran fine. Another person with MSVC .NET 2003 ran this code
>and he reported the same problem of crashing with optimizations turned on.
>
>Is this really an optimization bug, or is it possible that I am doing something
>wrong with the compiler settings? If this is indeed an optimization bug, how can
>I find out if Microsoft is already aware of it? If they are not aware of it, how
>can I report it to them?
>
>#include <stdio.h>
>
>unsigned int a[144];
>
>void init ()
>{
> unsigned int i;
> for (i = 0; i < 144; i++)
> a[i] = 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;
>}
It's definitely a serious bug. Here is the assembly output. It looks to me
like the optimizer noticed that the loop only iterates once and yet we branch
back up anyway. I think the mov is fine, it's just putting an 11 into the
register.
; 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[i] = 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
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.