3

I realize that this results in undefined behavior:

const int x = 12;
*const_cast<int*>(&x) = 13;

But does gcc do anything to prevent this from killing you, or does it just let you stand back and say "Hey you know better".

Maybe it just silently removes the const modifier in the whole program or something (I don't know I am just guessing here).

Any thoughts?

DarthRubik
  • 3,927
  • 1
  • 18
  • 54
  • 3
    When you use `const_cast` (or `reinterpret_cast` or C-style casts for that matter) you're telling the compiler "I know what I'm doing, back off". If you don't actually know what you're doing, then that will come back and bite you in the behinds. – Some programmer dude Apr 16 '16 at 22:11
  • And no, it doesn't "silently removes the const modifier in the whole program", it's just tells the compiler to shut up in that single place. – Some programmer dude Apr 16 '16 at 22:12
  • Why should it do any such thing? What would be the use of such a facility? Wouldn't you rather know sooner than later that your code isn't portable? – Kerrek SB Apr 16 '16 at 22:12
  • So gcc lets you do whatever you want (even if the original variable is completely optimized away?) – DarthRubik Apr 16 '16 at 22:12
  • I am just curious, I was not planning on actually doing this anywhere – DarthRubik Apr 16 '16 at 22:13

3 Answers3

1

Indeed, you can cast away constness of a pointer:

5.2.11/7 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-qualifier may produce undefined behavior

If the object referred to is a const, this is undefined behavior

7.1.6.1/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.

And undefined behavior is... undefined:

1.3.24: behavior for which this International Standard imposes no requirements (...) 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).

So, let's imagine what could happen: may be it will work, may be it will segfault (for example, because the const data would be stored in a const memory segment), may be it will not work as expected (for example, the write is ignored), may be you can get a warning or an error at compilation. So the best is to avoid this !

Quote of the day: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off" - Bjarne Stroustrup

Christophe
  • 68,716
  • 7
  • 72
  • 138
0

gcc is known for regularly changing actual behaviour when encountering UB. Version 1 tried to run nethack and then printed "99 bottles". I remember at some moment a critical exploit has appeared in Linux kernel when gcc started optimizing away condition in a code something like

int x = s->x;
if(s != NULL) {

Because it assumed that when you dereference a pointer, you know it is non-NULL (otherwise it was UB by the standard).

bipll
  • 11,747
  • 1
  • 18
  • 32
0

Part of the point of undefined behaviour is that the compiler is allowed to do anything at all. I'll leave others to quote the standardese, and focus on the philosophy in your question.

Generally speaking, declaring a variable const, throwing away constness, and then doing something that modifies the const variable is one area where compilers will not do anything in particular to protect you - after all, if you are doing such things, there are many different things you might intend and a compiler (or the programmers developing it) have no reason to assume any of them.

In your example the code which defines x (as distinct from just declaring it) may well be in a different compilation unit than the code which uses the const_cast in order to modify it. (It depends on how declarations, definitions, and code are organised in your source files).

gcc is a compiler that, mostly, does not peak into compilation units of your projects other than the one it is compiling. Which means it has no way of detecting such cases in general, and no way of ensuring that what happens in one compilation unit is consistent (i.e. in a manner that protects you) with what happens in another. For example, it might optimise one function in one compilation unit based on the assumption that x is 12, so that function will never change its behaviour after the statement *const_cast<int*>(&x) = 13 is executed in another function.

Peter
  • 35,646
  • 4
  • 32
  • 74