Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
139 views
in Technique[技术] by (71.8m points)

c++ - Does the evil cast get trumped by the evil compiler?

This is not academic code or a hypothetical quesiton. The original problem was converting code from HP11 to HP1123 Itanium. Basically it boils down to a compile error on HP1123 Itanium. It has me really scratching my head when reproducing it on Windows for study. I have stripped all but the most basic aspects... You may have to press control D to exit a console window if you run it as is:

#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    char blah[6];
    const int IAMCONST = 3;
    int *pTOCONST;
    pTOCONST = (int *)  &IAMCONST;
    (*pTOCONST) = 7;
    printf("IAMCONST %d 
",IAMCONST);
    printf("WHATISPOINTEDAT %d 
",(*pTOCONST));
    printf("Address of IAMCONST %x   pTOCONST %x
",&IAMCONST, (pTOCONST));
    cin >> blah;    
    return 0;
}

Here is the output

IAMCONST 3
WHATISPOINTEDAT 7
Address of IAMCONST 35f9f0   pTOCONST 35f9f0

All I can say is what the heck? Is it undefined to do this? It is the most counterintuitive thing I have seen for such a simple example.

Update:

Indeed after searching for a while the Menu Debug >> Windows >> Disassembly had exactly the optimization that was described below.

    printf("IAMCONST %d 
",IAMCONST);
0024360E  mov         esi,esp 
00243610  push        3    
00243612  push        offset string "IAMCONST %d 
" (2458D0h) 
00243617  call        dword ptr [__imp__printf (248338h)] 
0024361D  add         esp,8 
00243620  cmp         esi,esp 
00243622  call        @ILT+325(__RTC_CheckEsp) (24114Ah) 

Thank you all!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Looks like the compiler is optimizing

printf("IAMCONST %d 
",IAMCONST);

into

printf("IAMCONST %d 
",3);

since you said that IAMCONST is a const int.

But since you're taking the address of IAMCONST, it has to actually be located on the stack somewhere, and the constness can't be enforced, so the memory at that location (*pTOCONST) is mutable after all.

In short: you casted away the constness, don't do that. Poor, defenseless C...

Addendum

Using GCC for x86, with -O0 (no optimizations), the generated assembly

main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $36, %esp
    movl    $3, -12(%ebp)
    leal    -12(%ebp), %eax
    movl    %eax, -8(%ebp)
    movl    -8(%ebp), %eax
    movl    $7, (%eax)
    movl    -12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    movl    -8(%ebp), %eax
    movl    (%eax), %eax
    movl    %eax, 4(%esp)
    movl    $.LC1, (%esp)
    call    printf

copies from *(bp-12) on the stack to printf's arguments. However, using -O1 (as well as -Os, -O2, -O3, and other optimization levels),

main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $20, %esp
    movl    $3, 4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    movl    $7, 4(%esp)
    movl    $.LC1, (%esp)
    call    printf

you can clearly see that the constant 3 is used instead.

If you are using Visual Studio's CL.EXE, /Od disables optimization. This varies from compiler to compiler.

Be warned that the C specification allows the C compiler to assume that the target of any int * pointer never overlaps the memory location of a const int, so you really shouldn't be doing this at all if you want predictable behavior.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...