Microsoft KB Archive/115701

From BetaArchive Wiki

BUG: /G3 Option Generates Bad Code for sscanf and Structures

Q115701

1.00 1.50 WINDOWS kbtool kbbuglist ---------------------------------------------------------------------- The information in this article applies to: - The Microsoft C/C++ Compiler (CL.EXE), included with: Microsoft Visual C++ for Windows, versions 1.0 and 1.5 ---------------------------------------------------------------------- SYMPTOMS ======== Compiling code which uses sscanf() to fill fields within a structure using the /G3 compiler option (generate 386 code) will cause the compiler to push incorrect values for the structure variables being passed to sscanf(). This may result in an access violation. RESOLUTION ========== There are two workarounds to this problem: 1. Compile with the /G2 instead of /G3 compiler switch. -or- 2. Create temporary pointers to store the addresses of the structure variables and pass those temporary pointers to sscanf(). typedef struct tagSIZE { int cx; int cy; } SIZE; char sz[256]; SIZE Size; void main( void ) { int *x, *y; strcpy(sz, "3,4" ); x=&Size.cx; y=&Size.cy; sscanf(sz, "%d,%d", x, y); } STATUS ====== Microsoft has confirmed this to be a problem in the products listed at the beginning of this article. We are researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available. This problem does not occur in the C/C++ 32-bit compiler, version 8.0. MORE INFORMATION ================ The following is the assembly code generated when the call to sscanf() is made from the sample code below. You can generate this output by compiling the code below with the /Fc compiler option. ;|*** sscanf( sz, "%d,%d", &Size.cx, &Size.cy ); ;Line 17 *** 000011 66 68 00 00 push OFFSET DGROUP:_Size *** 000015 68 00 00 push OFFSET DGROUP:$SG259 *** 000018 68 00 00 push OFFSET DGROUP:_sz *** 00001b e8 00 00 call _sscanf *** 00001e 83 c4 08 add sp,8 In the assembly code listed here, the optimizer is trying to push both cx and cy as a 32-bit word. This would work, if the function required integer variables as the parameters. The problem here is that the two parameters are supposed to be pointers. The compiler is trying to push one 32-bit offset onto the stack, which is incorrect. Now, look at the same code fragment compiled with the /G2 option: ;|*** sscanf( sz, "%d,%d", &Size.cx, &Size.cy ); ; Line 17 *** 000017 68 02 00 push OFFSET _Size+2 *** 00001a 68 00 00 push OFFSET _Size *** 00001d 68 00 00 push OFFSET L00259 *** 000020 68 00 00 push OFFSET _sz *** 000023 e8 00 00 call _sscanf *** 000026 83 c4 08 add sp,OFFSET 8 In this code, two separate values are correctly pushed as the addresses of cx and cy. Sample Code ----------- /* Compile options needed: /G3 /f- */ #include #include typedef struct tagSIZE { int cx; int cy; } SIZE; char sz[256]; SIZE Size; void main( void ) { strcpy( sz, "3,4" ); sscanf( sz, "%d,%d", &Size.cx, &Size.cy ); printf( "%d, %d\n", Size.cx, Size.cy ); } Additional reference words: 8.00 8.00c 1.00 1.50 KBCategory: kbtool kbbuglist KBSubcategory: CodeGen

Keywords : kb16bitonly
Issue type :
Technology :


Last Reviewed: December 22, 1999
© 2001 Microsoft Corporation. All rights reserved. Terms of Use.