const cast to a global var and program crashed (C++)

心不动则不痛 提交于 2020-01-10 17:04:04

问题


int main()
{
    const int maxint=100;//The program will crash if this line is put outside the main
    int &msg=const_cast<int&>(maxint);  
    msg=200;  
    cout<<"max:"<<msg<<endl; 
    return 0;
}

The function will run ok if the 'const int maxint=100;' definition is put inside the main function but crash and popup a error message said "Access Violation" if put outside.

Someone says it's some kind of 'undefined behavior', and i want to know the exact answer and how i can use the const cast safely?


回答1:


They are correct, it is undefined behaviour. You're not allowed to modify the value of a const variable, which is the danger of casting away the constness of something: you better know it's not really const.

The compiler, seeing that maxint is const and should never be modified, doesn't even have to give it an address. It can just replace all the uses of maxint with 100 if it sees fit. Also it might just put the constant in to a portion of memory that is read-only, as Matteo Italia points out, which is probably what's happening for you. That's why modifying it produces undefined behaviour.

The only way you can safely cast away the constness of a variable is if the variable is not actually const, but the const qualifier was added to a non-const variable, like this:

int f(const int& x) {
    int& nonconst = const_cast<int&>(x);

    ++nonconst;
}

int blah = 523;

f(blah); // this is safe

const int constblah = 123;

f(constblah); // this is undefined behaviour

Think about this example, which compiles perfectly:

int f(const int& x) {
    int& nonconst = const_cast<int&>(x);

    ++nonconst;
}

int main() {
    f(4); // incrementing a number literal???
}

You can see how using const_cast is pretty dangerous because there's no way to actually tell whether a variable is originally const or not. You should avoid using const_cast when possible (with functions, by just not accepting const parameters).




回答2:


Modifying an object that is const (with the exception of mutable members) results in undefined behavior (from the C++03 standard):

7.1.5.1/4 "The cv-qualifiers"

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.

The above undefined behavior is specifically called out in the standard's section on const_cast:

5.2.11/7 "Const cast"

[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). ]

So, if you have a const pointer or reference to an object that isn't actually const, you're allowed to write to that object (by casting away the constness), but not if the object really is const.

The compiler is permitted to place const objects in read-only storage, for example. It doesn't have to though, and apparently doesn't for your test code that doesn't crash.




回答3:


You are only allowed to cast away constness of an object which is known not to be const. For example, an interface may pass objects through using a const pointer or a const reference but you passed in an object which isn't const and want/need to modify it. In this case it may be right thing to cast away constness.

On the other hand, casting away constness of an object which was const all the way can land you in deep trouble: when accessing this object, in particular when writing to it, the system may cause all kinds of strange things: the behavior is not defined (by the C++ standard) and on a particular system it may cause e.g. an access violation (because the address of the object is arranged to be in a read-only area).

Note that despite another response I saw const objects need to get an address assigned if the address is ever taken and used in some way. In your code the const_cast<int&>(maxint) expression essentially obtains the address of your constant int which is apparently stored in a memory area which is marked to be read-only. The interesting aspect of your code snippet is that it is like to apparently work, especially when turning on optimization: the code is simple enough that the compiler can tell that the changed location isn't really used and doesn't actually attempt to change the memory location! In this case, no access violation is reported. This is what apparently is the case when the constant is declared inside the function (although the constant may also be located on the stack which typically can't be marked as read-only). Another potential outcome of your code is (independent of whether the constant is declared inside the function or not) is that is actually changed and sometimes read as 100 and in other contexts (which in some way or another involve the address) as 200.



来源:https://stackoverflow.com/questions/8663290/const-cast-to-a-global-var-and-program-crashed-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!