Modifying a const int in C++ [duplicate] - c++

This question already has answers here:
Can we change the value of an object defined with const through pointers?
(11 answers)
Why can I change a local const variable through pointer casts but not a global one in C?
(7 answers)
Closed 9 years ago.
running the following code shows that &x=ptr, so how come x and *ptr are not equal?
const int x=10;
int* ptr =(int*) &x;
*ptr = (*ptr)+1;
cout << &x << " " << x << " " << ptr <<" " <<*ptr; //output : 0012FF60 10 0012FF60 11

The C++ implementation is only required to make a program work if you obey the rules. You violated the rules. The C++ implementation likely behaved this way:
Because x is declared const, the C++ implementation knows its value cannot change as long as you obey the rules. So, wherever x is used, the C++ implementation uses 10 without bothering to check whether x has changed.
Because *ptr points to a non-const int, stores to it and reads from it are actually performed. These “work” because the memory it points to (where x is represented) is not actually marked read-only by the operating system. Thus, you are able to make modifications in spite of the fact that you are not supposed to.
Observe that the behavior of the C++ implementation would work if you obeyed the rules. If you had not modified x, then using 10 for x wherever it appeared would have worked normally. Or, if you had not declared x to be const, then the C++ implementation would not have assumed it would always be 10, so it would get the changed value whenever x was accessed. This is all the C++ standard requires of an implementation: That it work if you follow the rules.
When you do not follow the rules, a C++ implementation may break in seemingly inconsistent ways.

You're modifying an object declared const. This is undefined behavior; the program is not required to do anything sensible. It could appear to work fine, or give subtly wrong answers, or segfault, or execute arbitrary code supplied by an attacker. The usual hyperbole is that the program is allowed to make demons fly out your nose.

Related

I have 2 pieces of c++ code that should work the same [duplicate]

This question already has answers here:
Modifying a const through a non-const pointer
(6 answers)
Closed 3 years ago.
This is the first piece of code, that outputs 44:
const int a[] = {3};
int* b = (int*)&a[0];
*b = 4;
cout << a[0] << *b;
And this is the second, that outputs 34:
const int a = 3;
int* b = (int*)&a;
*b = 4;
cout << a << *b;
I have no ideea why is there a difference. Can you guys explain this?
A pointer to a variable declared as const can be assigned only to a pointer that is also declared as const. You are breaking the rule and ideally your compiler should prevent you from doing so.
none of gcc, clang, and MSVC prevent such a mistake and as mentioned in the comments you have undefined behavior instead of at least a warning. However zapcc compiler will make your program to crash with a Segmentation fault.
Besides invoking "undefined behavior" by using casts to circumvent the compiler's checks to change the value of a const variable, the observed result can be explained with the optimizations the compiler likely did:
In the first case, you declare a const array, which likely ends up as data somewhere in RAM.
In the second case, you have a single scalar const value and the compiler probably decided to just use the constant's value which is known at compile time in the output instead of reading that known value from a RAM location. This optimization is also known as constant propagation.
If you didn't take the address of a in your code, it's value would probably not even have a location in data RAM allocated.

When is it okay to do/use something that has unspecified behaviour? [duplicate]

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 8 years ago.
In C++, there are things that come up that are somewhere between well-defined and undefined. Specifically, those are called implementation defined and unspecified. Right now, I'm interested in the unspecified stuff.
When is it okay to use such features, and when should they be avoided? Are there good examples of unspecified behaviour being a part of correct code? When, if ever, is it the best choice to make when writing software?
Definitions provided by Matt McNabb:
Undefined - anything at all can happen
Implementation-defined - a finite number of results are possible, and the compiler's documentation must say what happens
Unspecified - a finite number of results are possible -- usually the Standard describes the set of possible results
Well-defined - none of the above
Well-formed program - program that compiles without error (may exhibit undefined behaviour)
Follow-up question:
Do relaxed atomics count as unspecified or well-defined?
Marked as a duplicate of a question that talks about the same idea from a different perspective. The question marked as the same talks about the definition of unspecified behaviour, whereas here the question is about how and when to use it.
To answer the new question, "When is it OK to use unspecified behaviour?"
It may sound slightly facetious, but "any time it doesn't matter to you which option happens".
For example,
int foo() { cout << "foo"; return 1; }
int bar() { cout << "bar"; return 2; }
// ...
cout << (foo() + bar()) << "\n";
If you don't care whether you see "foobar3" or "barfoo3" then you could write this code. If it does matter then you would have to change it, e.g.
int i = foo(); i += bar(); cout << i << "\n";
The order is unspecified because it's good to leave freedom for the compiler to choose whichever order is optimal, in a more general case.

How is a variable at the same address producing 2 different values? [duplicate]

This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
Consider this :
#include <iostream>
using namespace std;
int main(void)
{
const int a1 = 40;
const int* b1 = &a1;
char* c1 = (char *)(b1);
*c1 = 'A';
int *t = (int*)c1;
cout << a1 << " " << *t << endl;
cout << &a1 << " " << t << endl;
return 0;
}
The output for this is :
40 65
0xbfacbe8c 0xbfacbe8c
This almost seems impossible to me unless compiler is making optimizations. How ?
This is undefined behavior, you are modifying a const variable so you can have no expectation as to the results. 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.
and even provides an example:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
In the standard definition of undefined behaviour in section 1.3.24, gives the following possible behaviors:
[...] 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). [...]
Your code has undefined behaviour, because you are modifying a constant object. Anything could happen, nothing is impossible.
When you qualify them variables const the compiler can assume a few things and generate code, this works fine providing you respect that agreement and not break it. When you've broken it, you'll get undefined behaviour.
Note that when const is removed, it works as expected; here's a live example.
As has been explained by others, modifying a const value results in undefined behavior and nothing more needs to be said - any result is possible, including complete nonsense or a crash.
If you're curious as to how this particular result came about, it's almost certainly due to optimization. Since you defined a to be const, the compiler is free to substitute the value 40 that you assigned to it whenever it wants; after all, its value can't change, right? This is useful when you're using a to define the size of an array for example. Even in gcc, which has an extension for variable-sized arrays, it's simpler for the compiler to allocate a constant-size array. Once the optimization exists it's probably applied consistently.

Can we use `const_cast` to modify a constant variable? [duplicate]

This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
int main()
{
const int ia = 10;
int *pia = const_cast<int*>(&ia);
*pia = 5;
std::cout << &ia << "\t" << pia <<endl;
std::cout << ia << "\t" << *pia <<endl;
return 0;
}
The output is:
0x28fef4 0x28fef4
10 5
*pia and ia have the same address, but they have different values. My purpose is to use const_cast to modify a constant value, but as the result shows that it does not work.
Does anyone know why?
The reason why you see 10 printed for ia is most likely the compiler optimization: it sees a const object, decides that it's not going to change, and replaces the last printout with this:
cout<< 10 <<" "<<*ppa<<endl;
In other words, the generated code has the value of the const "baked into" the binary.
Casting away the const-ness of an object that has originally been declared as const and writing to that object is undefined behavior:
$5.2.11/7 - Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier68) may produce undefined behavior (7.1.5.1).
Depending on the platform, const objects may be placed in a protected region of memory, to which you cannot write. Working around the const-ness in the type system may help your program compile, but you may see random results or even crashes.
It is undefined behaviour to modify a constant value. Don't do it. If you need to modify the value, don't declare it as const.

Casting a const int to a pointer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Modifying a const through a non-const pointer
I have the following code:
const int x = 5;
int *p = (int*)&x;
*p = 2; // Line 1
cout << x << " - " << *p << endl;
cout << &x << " - " << p << endl;
And got the results:
5 - 2
0012FF28 - 0012FF28
I know the code is weird and should never do it. But I wondered why the same address but got different result? And where the Line 1 store the number 2?
Because changing the value of an inherently const variable in anyway is Undefined Behavior[Ref #1].
Once you did:
*p = 2; // Line 1
All bets are off, and your code is no longer a valid C++ code, You cannot expect any particular behavior once that line was written. To speculate why an Undefined Behavior gives any particular behavior is pointless because it is allowed to show any behavior[Ref #2] that is the meaning of Undefined Behavior.
[Ref #1]
C++03 Standard 7.1.5.1 The cv-qualifiers:
Para 4:
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
[Ref #2]
C++03 Standard 1.3.24:
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).
Declaring something const gives the compiler permission to assume that that value will not change. This means that they can use an "immediate" instruction to load the value 5, rather than referencing the location (if any) assigned to x.
Further, modifying a const violates the assurance you gave the compiler that that "variable" would not be modified, and could produce a variety of unanticipated behaviors.
while some compilers do allocate an address for const values, it is a big no-no to access it. the reason you get 5-2 is because the compiler is replacing x directly with 5, even though you modified the address where x would have been given an address if it were not const and unless you access x's value through p* you are going to get 5 every time no matter what you do - also, p* may yield an undefined value since the getting the address of a const may actually fail with some compilers (and i think it should with all of them, personally)