Why is the result different even though address is same? [duplicate] - c++

Code
#include <iostream>
using namespace std;
int main() {
const int N = 22;
int * pN = const_cast<int*>(&N);
*pN = 33;
cout << N << '\t' << &N << endl;
cout << *pN << '\t' << pN << endl;
}
Output
22 0x22ff74
33 0x22ff74
Why are there two different values at the same address?

Why are there two different datas at the same address?
There aren't. The compiler is allowed to optimize any mention of a const to be as though you had written its compile-time value in there.
Note that the compiler is also allowed to generate code that erases your hard disk when you run it if you do nasty tricks like writing to memory reserved for consts.

You get undefined behavior on the line *pN = 33;, because you're modifying a const value. Anything can happen. Don't do it.
Likely, though, your compiler simply optimized. In the line:
cout << N << '\t' << &N << endl;
It knows N is a constant expression with the value 22, so just changes the line to:
cout << 22 << '\t' << &N << endl;
And on your next line, you fetch the value at the address of N, which you "set" to 33. (But really, all you did was remove any guarantees about the state of your program.)

By stating that N is const, you have promised that you won't modify it. And then you go and modify it. This breaks one of the assumptions the compiler is making, and as a result, the program behaves incorrectly.
This is referred to as "undefined behavior" - after violating an assumption in the language, the behavior of the program is completely undefined. It need not have produced that output - it could've produced 33 for both, or 42, or crashed, or erased your hard drive, or summoned demons through your nasal passages. So, don't modify const values :)

int * pN = const_cast<int*>(&N);
*pN = 33;
Your code invokes Undefined Behavior1 because you are modifying the content of a const qualified variable/object.
1)
Undefined Behavior: Behavior, such as might arise upon use of an
erroneous program construct or of erroneous data, for which the
Standard imposes no requirements.[Note: permissible undefined behavior
ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a
documented manner characteristic of the environment (with or without
the issuance of a diagnostic message), to terminating a translation
or execution (with the issuance of a diagnostic message).

You can declare N as volatile, to force the compiler to fetch the current value from the variable's memory location.
volatile const int N = 22;

const_cast in your code, just hands over a pointer 'Pn' to 'N' through which 'N' can be modified. The address of 'N' remains the same as the handed over pointer 'Pn'

I had the same question (Why am I not able to modify the contents of const int even with const_cast<int*>?) . I think answered here wonderfully by everyone. Just adding the assembly output from compiler
This is my original code
const int y = 7;
int* a = new int;
a = const_cast<int*>(&y);
*a = 8;
std::cout << (int)*(&y) << std::endl;
This is the assembly output
std::cout << (int)*(&y) << std::endl;
00381CB6 push offset std::endl<char,std::char_traits<char> > (03813C5h)
**00381CBB push 7**
00381CBD mov ecx,dword ptr [_imp_?cout#std##3V?$basic_ostream#DU?$char_traits#D#std###1#A (03900ACh)]
00381CC3 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900B8h)]
00381CC9 mov ecx,eax
00381CCB call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900BCh)]
So the compiler will just replace the const variables with its actual value during compile time.

Related

How can cpp show 2 different values at the same memory location after using const_cast on a const int variable [duplicate]

Code
#include <iostream>
using namespace std;
int main() {
const int N = 22;
int * pN = const_cast<int*>(&N);
*pN = 33;
cout << N << '\t' << &N << endl;
cout << *pN << '\t' << pN << endl;
}
Output
22 0x22ff74
33 0x22ff74
Why are there two different values at the same address?
Why are there two different datas at the same address?
There aren't. The compiler is allowed to optimize any mention of a const to be as though you had written its compile-time value in there.
Note that the compiler is also allowed to generate code that erases your hard disk when you run it if you do nasty tricks like writing to memory reserved for consts.
You get undefined behavior on the line *pN = 33;, because you're modifying a const value. Anything can happen. Don't do it.
Likely, though, your compiler simply optimized. In the line:
cout << N << '\t' << &N << endl;
It knows N is a constant expression with the value 22, so just changes the line to:
cout << 22 << '\t' << &N << endl;
And on your next line, you fetch the value at the address of N, which you "set" to 33. (But really, all you did was remove any guarantees about the state of your program.)
By stating that N is const, you have promised that you won't modify it. And then you go and modify it. This breaks one of the assumptions the compiler is making, and as a result, the program behaves incorrectly.
This is referred to as "undefined behavior" - after violating an assumption in the language, the behavior of the program is completely undefined. It need not have produced that output - it could've produced 33 for both, or 42, or crashed, or erased your hard drive, or summoned demons through your nasal passages. So, don't modify const values :)
int * pN = const_cast<int*>(&N);
*pN = 33;
Your code invokes Undefined Behavior1 because you are modifying the content of a const qualified variable/object.
1)
Undefined Behavior: Behavior, such as might arise upon use of an
erroneous program construct or of erroneous data, for which the
Standard imposes no requirements.[Note: permissible undefined behavior
ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a
documented manner characteristic of the environment (with or without
the issuance of a diagnostic message), to terminating a translation
or execution (with the issuance of a diagnostic message).
You can declare N as volatile, to force the compiler to fetch the current value from the variable's memory location.
volatile const int N = 22;
const_cast in your code, just hands over a pointer 'Pn' to 'N' through which 'N' can be modified. The address of 'N' remains the same as the handed over pointer 'Pn'
I had the same question (Why am I not able to modify the contents of const int even with const_cast<int*>?) . I think answered here wonderfully by everyone. Just adding the assembly output from compiler
This is my original code
const int y = 7;
int* a = new int;
a = const_cast<int*>(&y);
*a = 8;
std::cout << (int)*(&y) << std::endl;
This is the assembly output
std::cout << (int)*(&y) << std::endl;
00381CB6 push offset std::endl<char,std::char_traits<char> > (03813C5h)
**00381CBB push 7**
00381CBD mov ecx,dword ptr [_imp_?cout#std##3V?$basic_ostream#DU?$char_traits#D#std###1#A (03900ACh)]
00381CC3 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900B8h)]
00381CC9 mov ecx,eax
00381CCB call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900BCh)]
So the compiler will just replace the const variables with its actual value during compile time.

Does a const variable store the value in the variable?

I was messing around in C++ and wrote this code
#include <iostream>
int main() {
const int x = 10;
const int* ptr = &x;
*((int*)ptr) = 11;
std::cout << "ptr -> " << ptr << " -> " << *((int*)ptr) << std::endl;
std::cout << "x -> " << &x << " -> " << x << std::endl;
}
Interestingly, the output in the console is:
ptr -> 00CFF77C -> 11
x -> 00CFF77C -> 10
I checked the value at the memory address of ptr and the value is 11, so does this imply that const variables store the value in them, and not in memory? And if this were the case, why have a memory address storing the value?
Your code has Undefined Behavior.
x is a compile time constant, so the compiler expects it to not change value at runtime. As such, the compiler is allowed to optimize code by substituting uses of x's value with the literal value 10 at compile time.
So, at the point where << x is used, your compiler is emitting code for << 10 instead.
But, since your code is also using &x, the compiler is required to make sure that x has a memory address accessible at runtime. That means allocating a physical int and initializing its value to 10. Which you are then fiddling with in an unsafe manner, despite the fact that most compilers will likely place that int in read-only memory.
That is why you are seeing the output you see. But you are lucky your code is not crashing outright, trying to assign a new value to a constant at runtime.
The behavior of a program that writes to a const variable is undefined. It could print "10", it could print "11", it could print "3822", it could crash, or it could make demons fly out of your nose.
That said, in this case the behavior makes perfect sense. The compiler knows x is never allowed to change, so it transforms your std::cout << x to basically std::cout << 10.

C++: assign a integer to an integer pointer [duplicate]

According to " How to get around the warning "rvalue used as lvalue"? ", Visual Studio will merely warn on code such as this:
int bar() {
return 3;
}
void foo(int* ptr) {
}
int main() {
foo(&bar());
}
In C++ it is not allowed to take the address of a temporary (or, at least, of an object referred to by an rvalue expression?), and I thought that this was because temporaries are not guaranteed to even have storage.
But then, although diagnostics may be presented in any form the compiler chooses, I'd still have expected MSVS to error rather than warn in such a case.
So, are temporaries guaranteed to have storage? And if so, why is the above code disallowed in the first place?
Actually, in the original language design it was allowed to take the address of a temporary. As you have noticed correctly, there is no technical reason for not allowing this, and MSVC still allows it today through a non-standard language extension.
The reason why C++ made it illegal is that binding references to temporaries clashes with another C++ language feature that was inherited from C: Implicit type conversion.
Consider:
void CalculateStuff(long& out_param) {
long result;
// [...] complicated calculations
out_param = result;
}
int stuff;
CalculateStuff(stuff); //< this won't compile in ISO C++
CalculateStuff() is supposed to return its result via the output parameter. But what really happens is this: The function accepts a long& but is given an argument of type int. Through C's implicit type conversion, that int is now implicitly converted to a variable of type long, creating an unnamed temporary in the process.
So instead of the variable stuff, the function really operates on an unnamed temporary, and all side-effects applied by that function will be lost once that temporary is destroyed. The value of the variable stuff never changes.
References were introduced to C++ to allow operator overloading, because from the caller's point of view, they are syntactically identical to by-value calls (as opposed to pointer calls, which require an explicit & on the caller's side). Unfortunately it is exactly that syntactical equivalence that leads to troubles when combined with C's implicit type conversion.
Since Stroustrup wanted to keep both features (references and C-compatibility), he introduced the rule we all know today: Unnamed temporaries only bind to const references. With that additional rule, the above sample no longer compiles. Since the problem only occurs when the function applies side-effects to a reference parameter, it is still safe to bind unnamed temporaries to const references, which is therefore still allowed.
This whole story is also described in Chapter 3.7 of Design and Evolution of C++:
The reason to allow references to be initialized by non-lvalues was to allow the distinction between call-by-value and call-by-reference to be a detail specified by the called function and of no interest to the caller. For const references, this is possible; for non-const references it is not. For Release 2.0 the definition of C++ was changed to reflect this.
I also vaguely remember reading in a paper who first discovered this behavior, but I can't remember right now. Maybe someone can help me out?
Certainly temporaries have storage. You could do something like this:
template<typename T>
const T *get_temporary_address(const T &x) {
return &x;
}
int bar() { return 42; }
int main() {
std::cout << (const void *)get_temporary_address(bar()) << std::endl;
}
In C++11, you can do this with non-const rvalue references too:
template<typename T>
T *get_temporary_address(T &&x) {
return &x;
}
int bar() { return 42; }
int main() {
std::cout << (const void *)get_temporary_address(bar()) << std::endl;
}
Note, of course, that dereferencing the pointer in question (outside of get_temporary_address itself) is a very bad idea; the temporary only lives to the end of the full expression, and so having a pointer to it escape the expression is almost always a recipe for disaster.
Further, note that no compiler is ever required to reject an invalid program. The C and C++ standards merely call for diagnostics (ie, an error or warning), upon which the compiler may reject the program, or it may compile a program, with undefined behavior at runtime. If you would like your compiler to strictly reject programs which produce diagnostics, configure it to convert warnings to errors.
You're right in saying that "temporaries are not guaranteed to even have storage", in the sense that the temporary may not be stored in addressable memory. In fact, very often functions compiled for RISC architectures (e.g. ARM) will return values in general use registers and would expect inputs in those registers as well.
MSVS, producing code for x86 architectures, may always produce functions that return their values on the stack. Therefore they're stored in addressable memory and have a valid address.
Temporary objects do have memory. Sometimes the compiler creates temporaries as well. In poth cases these objects are about to go away, i.e. they shouldn't gather important changes by chance. Thus, you can get hold of a temporary only via an rvalue reference or a const reference but not via a non-const reference. Taking the address of an object which about to go away also feels like a dangerous thing and thus isn't supported.
If you are sure you really want a non-const reference or a pointer from a temporary object you can return it from a corresponding member function: you can call non-const member functions on temporaries. And you can return this from this member. However, note that the type system is trying to help you. When you trick it you better know that what you are diing is the Right Thing.
As others mentioned, we all agreed temporaries do have storage.
why is it illegal to take the address of a temporary?
Because temporaries are allocated on stack, the compiler is free to use that address to any other purposes it wants to.
int foo()
{
int myvar=5;
return &myvar;
}
int main()
{
int *p=foo();
print("%d", *p);
return 0;
}
Let's say the address of 'myvar' is 0x1000. This program will most likely print 99 even though it's illegal to access 0x1000 in main(). Though, not necessarily all the time.
With a slight change to the above main():
int foo()
{
int myvar=5;
return &myvar; // address of myvar is 0x1000
}
int main()
{
int *p=foo(); //illegal to access 0x1000 here
print("%d", *p);
fun(p); // passing *that address* to fun()
return 0;
}
void fun(int *q)
{
int a,b; //some variables
print("%d", *q);
}
The second printf is very unlikely to print '5' as the compiler might have even allocated the same portion of stack (which contains 0x1000) for fun() as well. No matter whether it prints '5' for both printfs OR in either of them, it is purely an unintentional side effect on how stack memory is being used/allocated. That's why it's illegal to access an address which is not alive in the scope.
Temporaries do have storage. They are allocated on the stack of the caller (note: might be subject of calling convention, but I think they all use caller's stack):
caller()
{
callee1( Tmp() );
callee2( Tmp() );
}
Compiler will allocate space for the result Tmp() on stack of the caller. You can take address of this memory location - it'll be some address on stack of caller. What compiler does not guarantee is that it will preserve values at this stack address after callee returns. For example, compiler can place there another temporary etc.
EDIT: I believe, it's disallowed to eliminate code like this :
T bar();
T * ptr = &bar();
because it will very likely lead to problems.
EDIT: here is a little test:
#include <iostream>
typedef long long int T64;
T64 ** foo( T64 * fA )
{
std::cout << "Address of tmp inside callee : " << &fA << std::endl;
return ( &fA );
}
int main( void )
{
T64 lA = -1;
T64 lB = -2;
T64 lC = -3;
T64 lD = -4;
T64 ** ptr_tmp = foo( &lA );
std::cout << "**ptr_tmp = *(*ptr_tmp ) = lA\t\t\t\t**" << ptr_tmp << " = *(" << *ptr_tmp << ") = " << **ptr_tmp << " = " << lA << std::endl << std::endl;
foo( &lB );
std::cout << "**ptr_tmp = *(*ptr_tmp ) = lB (compiler override)\t**" << ptr_tmp << " = *(" << *ptr_tmp << ") = " << **ptr_tmp << " = " << lB << std::endl
<< std::endl;
*ptr_tmp = &lC;
std::cout << "Manual override" << std::endl << "**ptr_tmp = *(*ptr_tmp ) = lC (manual override)\t\t**" << ptr_tmp << " = *(" << *ptr_tmp << ") = " << **ptr_tmp
<< " = " << lC << std::endl << std::endl;
*ptr_tmp = &lD;
std::cout << "Another attempt to manually override" << std::endl;
std::cout << "**ptr_tmp = *(*ptr_tmp ) = lD (manual override)\t\t**" << ptr_tmp << " = *(" << *ptr_tmp << ") = " << **ptr_tmp << " = " << lD << std::endl
<< std::endl;
return ( 0 );
}
Program output GCC:
Address of tmp inside callee : 0xbfe172f0
**ptr_tmp = *(*ptr_tmp ) = lA **0xbfe172f0 = *(0xbfe17328) = -1 = -1
Address of tmp inside callee : 0xbfe172f0
**ptr_tmp = *(*ptr_tmp ) = lB (compiler override) **0xbfe172f0 = *(0xbfe17320) = -2 = -2
Manual override
**ptr_tmp = *(*ptr_tmp ) = lC (manual override) **0xbfe172f0 = *(0xbfe17318) = -3 = -3
Another attempt to manually override
**ptr_tmp = *(*ptr_tmp ) = lD (manual override) **0xbfe172f0 = *(0x804a3a0) = -5221865215862754004 = -4
Program output VC++:
Address of tmp inside callee : 00000000001EFC10
**ptr_tmp = *(*ptr_tmp ) = lA **00000000001EFC10 = *(000000013F42CB10) = -1 = -1
Address of tmp inside callee : 00000000001EFC10
**ptr_tmp = *(*ptr_tmp ) = lB (compiler override) **00000000001EFC10 = *(000000013F42CB10) = -2 = -2
Manual override
**ptr_tmp = *(*ptr_tmp ) = lC (manual override) **00000000001EFC10 = *(000000013F42CB10) = -3 = -3
Another attempt to manually override
**ptr_tmp = *(*ptr_tmp ) = lD (manual override) **00000000001EFC10 = *(000000013F42CB10) = 5356268064 = -4
Notice, both GCC and VC++ reserve on the stack of main hidden local variable(s) for temporaries and MIGHT silently reuse them. Everything goes normal, until last manual override: after last manual override we have additional separate call to std::cout. It uses stack space to where we just wrote something, and as a result we get garbage.
Bottom line: both GCC and VC++ allocate space for temporaries on stack of caller. They might have different strategies on how much space to allocate, how to reuse this space (it might depend on optimizations as well). They both might reuse this space at their discretion and, therefore, it is not safe to take address of a temporary, since we might try to access through this address the value we assume it still has (say, write something there directly and then try to retrieve it), while compiler might have reused it already and overwrote our value.

Cast from hexadecimal to unsigned int* in c++

I have an assignment that were supposed to evaluate some pointer manipulation expressions and memory leak situations in C/C++. There's one I'm stuck with:
unsigned int* pInt = (unsigned int*) 0x403004;
Right off the bat this is suspicious to me, but in the assignment this line is theoretically working, however running the program I'm get segfault right at this line.
The question is: Is this right or even is possible or the professor is just fooling us telling this is right? I've seen some examples and questions with string "hex" to int, but nothing regarding "pure hex" to int or int*
unsigned int* pInt = (unsigned int*) 0x403004;
Two things are suspicious here:
Unless, you are writing some specialized Software like device drivers or OS, or you are in some embedded or special system where memory is fixed, seeing memory address hardcoded is certainly suspicious. Your program will (at best) fail if it tries to access memory it doesn't have the access rights to.
On the right hand side, the compiler first deduces the value 0x403004 as in int and will correctly convert it to a pointer. Thus, your Segfault is probably as a result of the first point.
unsigned int* pInt = (unsigned int*) 0x403004;
Possible?: yes (compiles, builds just fine)
Is it right?: depends on what for. Evidently it is useful for illustration in a classroom assignment.
Is it recommended? no. It will invoke undefined behavior. You are creating a variable that points to a location in memory that you may or may not have rights to. If you never use it, fine. But if you do use it, the results are indeterminate.
it works fine only if that number represents an already allocated memory
eg:
#include <iostream>
int main()
{
int i = 7;
std::cout << "i: " << i << std::endl; // 7
std::cout << "&i: " << &i << std::endl; // in my case: 0018FF44
unsigned int* ptr = (unsigned int*)0x0018FF44; // it's ok
/*
this is just for explaining because the address of i may differ at anytime the program
launches thus 0018FF44 will no longer be assigned to i and consequently segfault.
the right thing is to make pointer points always to whatever i may take as an address.
to do so:
*/
//int* ptr = (unsigned int*)&i; // not i but the address of i
(*ptr)++;
std::cout << i << std::endl; // 8
// above we changed i through pointer ptr
int* pRandom = (int*)0xAB2FC0DE0; // this causes me segfault
*pRandom = 5; // segfault
std::cout << "*pRandom: " << *pRandom << std::endl; // segfault
std::cout << std::endl;
return 0;
}

mechanism for "undefined-ness" of modifying the value of a const

I have read, it is undefined in some C standards (perhaps 99?) what happens when a const is modified. But a student presented me with some code, which I modified.
I cannot see anything special about the address of the constant variable a. I verified that &a and b are the same, so the compiler is not subtly pointing to some other location.
Yet when I assign *b, the const value does not change.
I am not running with optimization. When I compile with the -g flag to debug and step into the code, I get the results I expect (the memory location of the variable a changes). Yet the code presented below does not reflect the updated value of a.
Is this that temps are now being placed in registers even in debug mode, with no optimization?
#include <iostream>
using namespace std;
int main(){
const int a = 15;
cout << a << '\n';
int * b= (int*)&a;
cout << &a << "\n";
cout << b << "\n";
*b = 20;
cout << *b << '\n';
cout << a << '\n';
int x = a;
cout << x << '\n';
x = *b;
cout << x << '\n';
return 1;
}
This is also undefined behavior in C++, we can see this by going to the draft C++ standard section 7.1.6.1 The cv-qualifiers paragraph 4 which says:
[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
Undefined behavior means the results are unpredictable which effectively means any result is possible even ones that at first glance defy intuition.
A quick experiment with godbolt using -O0 so there is no optimization going on shows the compiler is just using the literal value 15 for a instead of retrieving it from memory and printing that out:
movl $15, %esi #,
So the compiler is performing constant folding since it assumes that since a is constant it can just use the value 15 anywhere it sees a. Which is completely reasonable since you told it a was constant.