Is It Safe to Cast Away volatile? - c++

Most of the time, I am doing this way.
class a {
public:
~ a() {
i = 100; // OK
delete (int *)j; // Compiler happy. But, is it safe?
// The following code will lead compilation error : delete j;
}
private:
volatile int i;
volatile int *j;
};
int main() {
a aa;
}
However, I saw an article here:
https://www.securecoding.cert.org/confluence/display/seccode/EXP32-C.+Do+not+access+a+volatile+object+through+a+non-volatile+reference
Casting away volatile allows access to
an object through a non-volatile
reference. This can result in
undefined and perhaps unintended
program behavior.
So, what will be the workaround for my above code example?
Here is the error message I get if I use
delete j
Note that, this is output from VC6 (Don't ask why I am using VC6!)
c:\projects\a\a.cpp(5) : error C2664:
'delete' : cannot convert parameter 1
from 'volatile int *' to 'void *'
Conversion loses qualifiers

Nothing. If you don't access the volatile memory, the semantics of volatile are unaffected. If you accessed volatile memory through a casted non-volatile pointer, the compiler might optimize the reference away. If the value had changed, you'd have the wrong value. For some value of wrong. ;-)
The delete doesn't access the volatile memory, it just frees it. Sort of an uncommon thing to do with volatile memory.

deleteing a volatile would imply that you've serialized access to it so it is not, in fact, volatile any more. The proper way to remove the volatile (once you know it's safe) is with const_cast<int*>.
If the pointer, and not the int, is volatile, then you really meant int *volatile j. Moreover, if all the members of a class are volatile, you probably want to qualify the entire object at once, a volatile aa;.

It depends on the meaning you expect from your volatile variable. Right now, j is a pointer to a volatile integer; is that what you mean? If so, it's safe since you don't need to access the volatile value, just its address, which isn't volatile.
If, however, you meant that you want a volatile pointer to an integer, the required syntax is int* volatile j. In that case, it could be problematic to cast it to a non-volatile pointer first, but I don't think your compiler would complain if you tried to delete it as is. G++, for one, doesn't.

That should be fine, since you're not accessing the variable after casting away the volatile. However, I don't know why you'd get an error regardless. I tried that code myself, and everything seemed to go fine, what did you see happen?

Related

Can a pointer be volatile?

Consider the following code:
int square(volatile int *p)
{
return *p * *p;
}
Now, the volatile keyword indicates that the value in a
memory location can be altered in ways unknown to the compiler or have
other unknown side effects (e.g. modification via a signal interrupt,
hardware register, or memory mapped I/O) even though nothing in the
program code modifies the contents.
So what exactly happens when we declare a pointer as volatile?
Will the above mentioned code always work, or is it any different from this:
int square(volatile int *p)
{
int a = *p;
int b = *p
return a*b;
}
Can we end up multiplying different numbers, as pointers are volatile?
Or is there better way to do so?
Can a pointer be volatile?
Absolutely; any type, excluding function and references, may be volatile-qualified.
Note that a volatile pointer is declared T *volatile, not volatile T*, which instead declares a pointer-to-volatile.
A volatile pointer means that the pointer value, that is its address and not the value pointed to by, may have side-effects that are not visible to the compiler when it's accessed; therefore, optimizations deriving from the "as-if rule" may not be taken into account for those accesses.
int square(volatile int *p) { return *p * *p; }
The compiler cannot assume that reading *p fetches the same value, so caching its value in a variable is not allowed. As you say, the result may vary and not be the square of *p.
Concrete example: let's say you have two arrays of ints
int a1 [] = { 1, 2, 3, 4, 5 };
int a2 [] = { 5453, -231, -454123, 7565, -11111 };
and a pointer to one of them
int * /*volatile*/ p = a1;
with some operation on the pointed elements
for (int i = 0; i < sizeof(a1)/sizeof(a1[0]); ++i)
*(p + i) *= 2;
here p has to be read each iteration if you make it volatile because, perhaps, it may actually point to a2 due to external events.
Yes, you can of course have a volatile pointer.
Volatile means none more and none less than that every access on the volatile object (of whatever type) is treated as a visible side-effect, and is therefore exempted from optimization (in particular, this means that accesses may not be reordered or collapsed or optimized out alltogether). That's true for reading or writing a value, for calling member functions, and of course for dereferencing, too.
Note that when the previous paragraph says "reordering", a single thread of execution is assumed. Volatile is no substitute for atomic operations or mutexes/locks.
In more simple words, volatile generally translates to roughly "Don't optimize, just do exactly as I say".
In the context of a pointer, refer to the exemplary usage pattern given by Chris Lattner's well-known "What every programmer needs to know about Undefined Behavior" article (yes, that article is about C, not C++, but the same applies):
If you're using an LLVM-based compiler, you can dereference a "volatile" null pointer to get a crash if that's what you're looking for, since volatile loads and stores are generally not touched by the optimizer.
Yes. int * volatile.
In C++, keywords according to type/pointer/reference go after the token, like int * const is constant pointer to integer, int const * is pointer to constant integer, int const * const is constant pointer to constant integer e.t.c. You can write keyword before the type only if it's for the first token: const int x is equal to int const x.
The volatile keyword is a hint for the compiler (7.1.6.1/7):
Note:
volatile
is a hint to the implementation to avoid aggressive optimization involving the object
because the value of the object might be changed by means undetectable by an implementation. Furthermore,
for some implementations,
volatile
might indicate that special hardware instructions are required to access
the object. See
1.9
for detailed semantics. In general, the semantics of
volatile
are intended to be the
same in C
++
as they are in C.
— end note
]
What does it mean? Well, take a look at this code:
bool condition = false;
while(!condition)
{
...
}
by default, the compiler will easilly optimize the condition out (it doesn't change, so there is no need to check it at every iteration). If you, however, declare the condition as volatile, the optimization will not be made.
So of course you can have a volatile pointer, and it is possible to write code that will crash because of it, but the fact that a variable is volative doesn't mean that it is necessarily going to be changed due to some external interference.
Yes, a pointer can be volatile if the variable that it points to can change unexpectedly even though how this might happen is not evident from the code.
An example is an object that can be modified by something that is external to the controlling thread and that the compiler should not optimize.
The most likely place to use the volatile specifier is in low-level code that deals directly with the hardware and where unexpected changes might occur.
You may be end up multiplying different numbers because it's volatile and could be changed unexpectedly. So, you can try something like this:
int square(volatile int *p)
{
int a = *p;
return a*a;
}
int square(volatile int *p)
{
int a = *p;
int b = *p
return a*b;
}
Since it is possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square! The correct way to code this is:
long square(volatile int *p)
{
int a;
a = *p;
return a * a;
}

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

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?
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).
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.
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.

Casting a pointer to a volatile void** in C++

I have fairly decent C++ skills, but this one cast has been giving me issues. I have a function that takes in the following parameters: (volatile void **, void * , void*). I have 3 int* variables and I am trying to pass them in as (&var1, var2, var3). However, I am getting the following error: Cannot convert parameter 1 from int** to volatile void**. Is there a specific cast that needs to be made to allow for this? Below is a snippet of code that I am using. Any help is greatly appreciated.
int* pVal = InterlockedCompareExchangePointer(&cur_val, new_val, old_val);
This is being done in VS2010 on a windows XP machine.
The first one should be volatile void ** and you have int **. You can either just cast to volatile void**, or (better) declare the original variable as volatile and then cast.
volatile means that the variable can be changed elsewhere outside of your code, and basically it means that the variable won't be optimized, but since your original variable is not defined as volatile it might still be optimized, and you would get incorrect results.
You can do a const_cast, but the best thing you can do is to declare your variable a volatile int* (i.e. pointer to volatile int) because otherwise the result might be undefined.
InterlockedCompareExchangePointer does an operation that may be beyond the optimizer's scope to analyze, so it's important that the variable is volatile to make sure its value is fetched from memory (and not cached in registers etc.) each time it is being used.
In addition to declaring the int as volatile, you still need to cast it as:
int* pVal = (int *)InterlockedCompareExchangePointer((void **)&cur_val, (void *)new_val, (void *)old_val);
Note the cast of the value returned from the function too. It returns a void *, so it must be cast to int *.
C++ requires explicit casts.

const casting an int in a class vs outside a class

I read on the wikipedia page for Null_pointer that Bjarne Stroustrup suggested defining NULL as
const int NULL = 0;
if "you feel you must define NULL." I instantly thought, hey.. wait a minute, what about const_cast?
After some experimenting, I found that
int main() {
const int MyNull = 0;
const int* ToNull = &MyNull;
int* myptr = const_cast<int*>(ToNull);
*myptr = 5;
printf("MyNull is %d\n", MyNull);
return 0;
}
would print "MyNull is 0", but if I make the const int belong to a class:
class test {
public:
test() : p(0) { }
const int p;
};
int main() {
test t;
const int* pptr = &(t.p);
int* myptr = const_cast<int*>(pptr);
*myptr = 5;
printf("t.p is %d\n", t.p);
return 0;
}
then it prints "t.p is 5"!
Why is there a difference between the two? Why is "*myptr = 5;" silently failing in my first example, and what action is it performing, if any?
First of all, you're invoking undefined behavior in both cases by trying to modify a constant variable.
In the first case the compiler sees that MyNull is declared as a constant and replaces all references to it within main() with a 0.
In the second case, since p is within a class the compiler is unable to determine that it can just replace all classInstance.p with 0, so you see the result of the modification.
Firstly, what happens in the first case is that the compiler most likely translates your
printf("MyNull is %d\n", MyNull);
into the immediate
printf("MyNull is %d\n", 0);
because it knows that const objects never change in a valid program. Your attempts to change a const object leads to undefined behavior, which is exactly what you observe. So, ignoring the undefined behavior for a second, from the practical point of view it is quite possible that your *myptr = 5 successfully modified your Null. It is just that your program doesn't really care what you have in your Null now. It knows that Null is zero and will always be zero and acts accordingly.
Secondly, in order to define NULL per recommendation you were referring to, you have to define it specifically as an Integral Constant Expression (ICE). Your first variant is indeed an ICE. You second variant is not. Class member access is not allowed in ICE, meaning that your second variant is significantly different from the first. The second variant does not produce a viable definition for NULL, and you will not be able to initialize pointers with your test::p even though it is declared as const int and set to zero
SomeType *ptr1 = Null; // OK
test t;
SomeType *ptr2 = t.p; // ERROR: cannot use an `int` value to initialize a pointer
As for the different output in the second case... undefined behavior is undefined behavior. It is unpredictable. From the practical point of view, your second context is more complicated, so the compiler was unable to prefrom the above optimization. i.e. you are indeed succeeded in breaking through the language-level restrictions and modifying a const-qualified variable. Language specification does not make it easy (or possible) for the compilers to optimize out const members of the class, so at the physical level that p is just another member of the class that resides in memory, in each object of that class. Your hack simply modifies that memory. It doesn't make it legal though. The behavior si still undefined.
This all, of course, is a rather pointless exercise. It looks like it all began from the "what about const_cast" question. So, what about it? const_cast has never been intended to be used for that purpose. You are not allowed to modify const objects. With const_cast, or without const_cast - doesn't matter.
Your code is modifying a variable declared constant so anything can happen. Discussing why a certain thing happens instead of another one is completely pointless unless you are discussing about unportable compiler internals issues... from a C++ point of view that code simply doesn't have any sense.
About const_cast one important thing to understand is that const cast is not for messing about variables declared constant but about references and pointers declared constant.
In C++ a const int * is often understood to be a "pointer to a constant integer" while this description is completely wrong. For the compiler it's instead something quite different: a "pointer that cannot be used for writing to an integer object".
This may apparently seem a minor difference but indeed is a huge one because
The "constness" is a property of the pointer, not of the pointed-to object.
Nothing is said about the fact that the pointed to object is constant or not.
The word "constant" has nothing to do with the meaning (this is why I think that using const it was a bad naming choice). const int * is not talking about constness of anything but only about "read only" or "read/write".
const_cast allows you to convert between pointers and references that can be used for writing and pointer or references that cannot because they are "read only". The pointed to object is never part of this process and the standard simply says that it's legal to take a const pointer and using it for writing after "casting away" const-ness but only if the pointed to object has not been declared constant.
Constness of a pointer and a reference never affects the machine code that will be generated by a compiler (another common misconception is that a compiler can produce better code if const references and pointers are used, but this is total bogus... for the optimizer a const reference and a const pointer are just a reference and a pointer).
Constness of pointers and references has been introduced to help programmers, not optmizers (btw I think that this alleged help for programmers is also quite questionable, but that's another story).
const_cast is a weapon that helps programmers fighting with broken const-ness declarations of pointers and references (e.g. in libraries) and with the broken very concept of constness of references and pointers (before mutable for example casting away constness was the only reasonable solution in many real life programs).
Misunderstanding of what is a const reference is also at the base of a very common C++ antipattern (used even in the standard library) that says that passing a const reference is a smart way to pass a value. See this answer for more details.

C/C++: casting away volatile considered harmful?

(related to this question Is It Safe to Cast Away volatile?, but not quite the same, as that question relates to a specific instance)
Is there ever a case where casting away volatile is not considered a dangerous practice?
(one particular example: if there is a function declared
void foo(long *pl);
and I have to implement
void bar(volatile long *pl);
with part of my implementation requiring bar() to call foo(pl), then it seems like I can't get this to work as is, because the assumptions made by the compilation of foo() and the compilation of the caller of bar() are incompatible.)
As a corollary, if I have a volatile variable v, and I want to call foo(&v) with someone else's function void foo(long *pl), and that person tells me it's safe, I can just cast the pointer before the call, my instinct is to tell them they're wrong because there's no way to guarantee that, and that they should change the declaration to void foo(volatile long *pl) if they want to support the use of volatile variables. Which one of us is correct?
If the variable is declared volatile then it is undefined behaviour to cast away the volatile, just as it is undefined behaviour to cast away the const from a variable declared const. See Annex J.2 of the C Standard:
The behavior is undefined in the following circumstances:
...
— An attempt is made to modify an object defined with a const-qualified type through
use of an lvalue with non-const-qualified type (6.7.3).
— An attempt is made to refer to an object defined with a volatile-qualified type through
use of an lvalue with non-volatile-qualified type (6.7.3).
If, however, you just have a volatile pointer or a volatile reference to a non-volatile variable then you can freely cast away volatile.
volatile int i=0;
int j=0;
volatile int* pvi=&i; // ok
volatile int* pvj=&j; // ok can take a volatile pointer to a non-volatile object
int* pi=const_cast<int*>(pvi); // Danger Will Robinson! casting away true volatile
int* pj=const_cast<volatile int*>(pvj); // OK
*pi=3; // undefined behaviour, non-volatile access to volatile variable
*pj=3; // OK, j is not volatile
Casting away volatile would be ok, once the value is in fact no longer volatile. In SMP/multi-threading situations, this could become true after acquiring a lock (and passing a memory barrier, which is most often implicit in acquiring the lock).
So a typical pattern for this would be
volatile long *pl = /*...*/;
//
{
Lock scope(m_BigLock); /// acquire lock
long *p1nv = const_cast<long *>(p1);
// do work
} // release lock and forget about p1nv!
But I could come up with a number of other scenarios in which values stop being volatile. I won't suggest them here, as I'm sure you can come up with them yourself, if you know what you're doing. Otherwise, the locking scenarios seems solid enough to provide as an example
With a signature of foo(long *pl), the programmer is declaring that they are not expecting the pointed-to long value to change externally during the execution of foo. Passing a pointer to a long value that is being concurrently modified throughout an invocation might even lead to erroneous behavior if the compiler emits code that dereferences the pointer multiple times due to lack of registers and by it choosing not to store the value of the first dereference on the stack. For example, in:
void foo(long *pl) {
char *buf = (char *) malloc((size_t) *pl);
// ... busy work ...
// Now zero out buf:
long l;
for (l = 0; l < *pl; ++l) {
buf[l] = 0;
}
free(buf);
}
foo could overrun the buffer in the "zero out buf" step if the long value is increased while the busy work is being performed.
If the foo() function is supposed to atomically increment the long value pointed to by pl, then it would be incorrect for the function to take long *pl and not volatile long *pl because the function clearly requires that accesses of the long value be a sequence point. If foo() only atomically incremented, the function might work, but it would not be correct.
Two solutions to this problem have already been suggested in comments:
Wrap foo taking long * in an overload taking volatile long *:
inline void foo(volatile long *pvl) {
long l = *pvl;
foo(&l);
*pvl = l;
}
Change the declaration of foo to void foo(volatile long *pvl).