FIX: Setting Bitfields with /Oe Overwrites Stored BPLast reviewed: September 18, 1997Article ID: Q114074 |
6.00 6.00a 7.00 | 6.00 6.00a | 1.00
MS-DOS | OS/2 | WINDOWSkbtool kbfixlist kbbuglist The information in this article applies to:
SYMPTOMSReturning from a function which modifies bitfields of a global structure causes the system to hang, crash with a memory violation, or execute an invalid instruction.
CAUSEIncorrect code can be generated when bitfields of a global structure are modified and /Oe (global register allocation) optimization is used. For the problem to be reproduced, /Gt<n> (data size threshold) must be specified with n less than the size of the global struct. This incorrect code overwrites the value of BP pushed onto the stack on entry into the function. The sample code at the end of this article demonstrates the problem.
RESOLUTIONThere are a few possible ways to work around this problem.
STATUSMicrosoft has confirmed this to be a problem in the Microsoft products listed above. This is not a problem in Visual C++, 32-bit Edition. This problem was corrected in Visual C++ version 1.5.
Sample Code
/* Compile options needed: /AL /Oe /Fc /Gt14 Description: This code, when compiled with Microsoft C/C++ compilers previous to version 8.0c and with /Oe, overwrite a stored BP on the line indicated. Without /Oe, the problem does not occur. The printf's do not demonstrate the problem, it is the failure to return from the function call, or examination of the .COD listing, which demonstrates this. */ #include <stdio.h>struct test_struct { char *text; int iTest; unsigned unsigned_1:1; unsigned unsigned_2:1; unsigned unsigned_3:1; unsigned unsigned_4:1; unsigned unsigned_5:1; unsigned unsigned_6:1; unsigned unsigned_7:1; unsigned unsigned_8:1; unsigned unsigned_9:1; };static struct test_struct tst_strct[2];
void oe_error( int iX, char *text, int iTest, int test_1, int test_2, int test_3, int test_4, int test_5, int test_6, int test_7, int test_8, int test_9); void test(void); void main(int argc, char *argv){ int iTest_1; iTest_1 = 10; // The following is needed for creation of a stackframe in main(): if(iTest_1+argc < 10) { // will never be reached. test(); } test(); printf("It should be: iTest_1 = 10\n" ); printf(" It is: iTest_1 = %d\n", iTest_1); } // Take comment off following line to work around problem // #pragma optimize ( "e", off) void test(void){ int iX = 1; oe_error( iX, "TEXT", 5, 1, 1, 1, 1, 0, 0, 0, 0, 0);}
void oe_error( int iX, char *text, int iTest, int test_1, int test_2, int test_3, int test_4, int test_5, int test_6, int test_7, int test_8, int test_9) { tst_strct[iX].text = text; tst_strct[iX].iTest = iTest; tst_strct[iX].unsigned_1 = test_1; tst_strct[iX].unsigned_2 = test_2; tst_strct[iX].unsigned_3 = test_3; tst_strct[iX].unsigned_4 = test_4; tst_strct[iX].unsigned_5 = test_5; tst_strct[iX].unsigned_6 = test_6; tst_strct[iX].unsigned_7 = test_7; tst_strct[iX].unsigned_8 = test_8; tst_strct[iX].unsigned_9 = test_9; /* The stored BP is overwritten here */}
// Uncomment for work around // #pragma optimize ("", on) /* The code which causes BP to be overwritten comes immediately after the line tst_strct[iX].unsigned_9 = test_9; in the .COD listing. The problem is that this code does *** 000099 81 c3 06 00 add bx,OFFSET $S175_tst_strct+6 *** 00009d 89 5e fe mov WORD PTR [bp-2],bx >> *** 0000a0 8c 5e 00 mov WORD PTR [bp],ds>> This will overwrite the stored BP, so that BP is not correctly >> retrieved at the end of this function.
See the .COD listing produced when compiling for more information. */ |
Additional reference words: 8.00 1.00
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |