Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

const_cast and UB

$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). ]"

The wordings of this section (C++03) are surprising to me. What is suprising are two things.

a) Firstly, the use of 'may'. Why is it 'may'? Other places in the Standard are very definitive about the undefined behavior

b) Why is that the casting away the constness of a originally const object not straight away 'undefined behavior'. Why is it that a write is required for UB to be triggered?

like image 504
Chubsdad Avatar asked Oct 28 '10 11:10

Chubsdad


2 Answers

a) Firstly, the use of 'may'. Why is it 'may'? Other places in the Standard are very definitive about the undefined behavior

Don't look too deeply into the use of the word may here. The point is, casting away constness in this case causes undefined behavior.

The C++ standard uses "may" or "might" often, as in:

1.3.12: Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior.

Emphasis mine. Basically, the standard uses the word "may" as in "is allowed to".

b) Why is that the casting away the constness of a originally const object not straight away 'undefined behavior'. Why is it that a write is required for UB to be triggered?

A write triggers UB because it's possible that const objects can be stored in read-only memory on certain platforms.

like image 155
Charles Salvia Avatar answered Sep 30 '22 08:09

Charles Salvia


My understanding is that it will only be UB if the object in question is fundamentally a const object rather than a const pointer or reference to an object which was not originally const.

The idea being that data that is fundamentally const could be loaded into a read-only portion of memory, and writing to that just isn't going to work. However, it's guaranteed to work properly if the object in question is fundamentally mutable.

Ex:

const int  x = 4;
const int *y = x;

*const_cast<int*>(x) = 3; // UB - the pointed-to object may 
                          // be in read-only memory or whatever.

int        a = 7;
const int *b = a;

*const_cast<int*>(b) = 6; // Not UB - the pointed-to object is 
                          // fundamentally mutable.

For a comment below, because code looks terrible in comments:

In §7.1.​5.1/4 of the standard, the example given is:

int i = 2;
const int * cip; // pointer to const int
cip = &i;        // OK: cv-qualified access path to unqualified
...
int* ip;
ip = const_cast <int *>( cip ); // cast needed to convert const int* to int*
*ip = 4;                        // defined: *ip points to i, a non-const object

So this is specifically allowed.

like image 25
Kaz Dragon Avatar answered Sep 30 '22 06:09

Kaz Dragon