Someone was asking questions about const_cast<>() a few days ago. I was not quite sure how it would work because I try to use as little of the C++ language as possible and it possible to get by in C++ without const_cast<>(). To find out exactly how it worked I tried it out with a test case. The following code gave the same output on g++ on Vista and OS X.
The output in both cases was Cannot happen: &i=0x22fe6c == ptr=0x22fe6c but i=3 != *ptr=22
int i = 3;
const int* ptr = &i;
*const_cast<int*>(ptr) = 11;
if (&i == ptr && i != *ptr) {
std::cout << "Cannot happen: &i=" << &i << " == ptr=" << ptr << " but i=" << i << " != *ptr=" << *ptr << std::endl;
}
How can a single memory address hold two different values?
The disassembly was
push %ebp
mov %esp,%ebp
sub $0x18,%esp
int i = 3;
movl $0x3,0xfffffffc(%ebp) (i in bp-4)
const int* ptr = &i;
lea 0xfffffffc(%ebp),%eax (&i in eax)
mov %eax,0xfffffff8(%ebp) (ptr in bp-8)
*const_cast<int*>(ptr) = 11;
mov 0xfffffff8(%ebp),%eax (ptr in eax)
movl $0xb,(%eax) (*ptr set to 11)
if (&i == ptr && i != *ptr)
lea 0xfffffffc(%ebp),%eax
cmp 0xfffffff8(%ebp),%eax
jne 0x403214
mov 0xfffffff8(%ebp),%eax
mov (%eax),%eax
cmp 0xfffffffc(%ebp),%eax
je 0x403214
The disassembly matches the C++ code. i is stored at bp-4 and ptr is stored at bp-8 so the C++ code should work. The observed behaviour does not match the disassembly.
This cannot be right. I guess I found a bug in g++.
4 comments:
Interesting. What versions of g++ and the standard library are you using?
I compiled and ran the following:
#include <iostream>
int main(int argc, char** argv)
{
int i = 3;
const int* ptr = &i;
*const_cast<int*>(ptr) = 11;
if (&i == ptr && i != *ptr) {
std::cout << "Cannot happen: &i=" << &i << " == ptr=" << ptr << " but i=" << i << " != *ptr=" << *ptr << std::endl;
}
else
{
std::cout << "i = " << i << std::endl;
}
}
and got the output "i = 11".
This was on OSX 10.6.2, using g++ 4.2.1
Andy
I am using g++ 4.0.1 on OS X 10.5.8
However I just built and ran this code from the command line and it worked correctly.
The bug I was seeing must have been in Eclipse CDT which I had used to build and run the program on OS X and Vista.
user@ws:~/tmp/const_cast$ uname -a
Linux ws 2.6.28-13-generic #45-Ubuntu SMP Tue Jun 30 22:12:12 UTC 2009 x86_64 GNU/Linux
user@ws:~/tmp/const_cast$ g++ --version
g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
user@ws:~/tmp/const_cast$ cat main.cpp
#include <iostream>
int main()
{
int i = 3;
const int* ptr = &i;
*const_cast(ptr) = 11;
if (&i == ptr && i != *ptr)
std::cout << "Cannot happen: &i=" << &i << " == ptr=" << ptr << " but i=" << i << " != *ptr=" << *ptr << std::endl;
else
std::cout << "OK" << std::endl;
return 0;
}
user@ws:~/tmp/const_cast$ g++ main.cpp -o main
user@ws:~/tmp/const_cast$ ./main
OK
Vlad
Thanks for double checking the code.
See my previous comment. The problem is in Eclipse CDT or gdb.
How is the image recognition work?
-Peter
Post a Comment