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;
}
Related
The from_base function returns the memory address from the base to a selected
value in a program. I want to retrieve this value and return it in a function, however, I am getting a warning that says integer to pointer cast pessimism optimization opportunities.
DWORD chat::client() {
return *reinterpret_cast<DWORD*>(core::from_base(offsets::chat::client));
}
I am also getting this warning when casting a function from the program:
auto og_print = reinterpret_cast<chat::fn_print_chat>(core::from_base(offsets::chat::print));
I don't understand why I am getting a warning from clang-tidy about integer to pointer cast pessimism optimization opportunities
performance-no-int-to-ptr
I looked it up, but I can't figure it out. The code works, and gets the correct value. I am just concerned about the warning.
If a program performs a computation like:
char x[10],y[10];
int test(ptrdiff_t i)
{
int *p = x+i;
*p = 1;
y[1] = 2;
return *p;
}
a compiler would be reasonably entitled to assume that because p was formed via pointer arithmetic using x, it could not possible equal y+1, and thus the function would always return 1. If, however, the code had been written as:
char x[10],y[10];
int test(ptrdiff_t i)
{
int *p = (char*)((uintptr_t)x + i);
*p = 1;
y[1] = 2;
return *p;
}
then such an assumption would be far less reasonable, since unsigned numerical semantics would define the behavior of uintptr_t z = (uintptr_t)(y+1)-(uintptr_t)x as yielding a value such that x+z would equal (uintptr_t)(y+1).
I find the apparent caution clang exhibits here a bit surprising, given that clang is prone to assume that, given some pointer char*p, it's not possible for p to equal y if (uintptr_t)p to equal (uintptr_t)(x+10) and yet for p to equal y. The Standard doesn't forbid such an assumption, but then again it also wouldn't forbid an assumption that code will never use the result of any integer-to-pointer conversion for any purpose other than comparisons with other pointers. Implementations that support type uintptr_t should of course offer stronger guarantees about round-tripped pointers which than merely saying they may be compared for equality with the originals, but the Standard doesn't require such treatment.
(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).
I've read the essay Surviving the Release Version.
Under the "Aliasing bugs" clause it says:
You can get tighter code if you tell
the compiler that it can assume no
aliasing....
I've also read Aliasing (computing).
What exactly is a variable alias? I understand it means using a pointer to a variable is an alias, but, how/why does it affect badly, or in other words - why telling the compiler that it can assume no aliasing would get me a "tighter code"
Aliasing is when you have two different references to the same underlying memory. Consider this made up example:
int doit(int *n1, int *n2)
{
int x = 0;
if (*n1 == 1)
{
*n2 = 0;
x += *n1 // line of interest
}
return x;
}
int main()
{
int x = 1;
doit(&x, &x); // aliasing happening
}
If the compiler has to allow for aliasing, it needs to consider the possibility that n1 == n2. Therefore, when it needs to use the value of *n1 at "line of interest", it needs to allow for the possibility it was changed by the line *n2 = 0.
If the compiler can assume no aliasing, it can assume at "line of interest" that *n1 == 1 (because otherwise we would not be inside the if). The optimizer can then use this information to optimize the code (in this case, change "line of interest" from following the pointer and doing a general purpose addition to using a simple increment).
Disallowing aliasing means if you have a pointer char* b, you can assume that b is the only pointer in the program that points to that particular memory location, which means the only time that memory location is going to change is when the programmer uses b to change it. The generated assembly thus doesn't need to reload the memory pointed to by b into a register as long as the compiler knows nothing has used b to modify it. If aliasing is allowed it's possible there's another pointer char* c = b; that was used elsewhere to mess with that memory
In C and C++ what do the following declarations do?
const int * i;
int * const i;
const volatile int ip;
const int *i;
Are any of the above declarations wrong?
If not what is the meaning and differences between them?
What are the useful uses of above declarations (I mean in which situation we have to use them in C/C++/embedded C)?
const int * i;
i is a pointer to constant integer. i can be changed to point to a different value, but the value being pointed to by i can not be changed.
int * const i;
i is a constant pointer to a non-constant integer. The value pointed to by i can be changed, but i cannot be changed to point to a different value.
const volatile int ip;
This one is kind of tricky. The fact that ip is const means that the compiler will not let you change the value of ip. However, it could still be modified in theory, e.g. by taking its address and using the const_cast operator. This is very dangerous and not a good idea, but it is allowed. The volatile qualifier indicates that any time ip is accessed, it should always be reloaded from memory, i.e. it should NOT be cached in a register. This prevents the compiler from making certain optimizations. You want to use the volatile qualifier when you have a variable which might be modified by another thread, or if you're using memory-mapped I/O, or other similar situations which could cause behavior the compiler might not be expecting. Using const and volatile on the same variable is rather unusual (but legal) -- you'll usually see one but not the other.
const int *i;
This is the same as the first declaration.
You read variables declarations in C/C++ right-to-left, so to speak.
const int *i; // pointer to a constant int (the integer value doesn't change)
int *const i; // constant pointer to an int (what i points to doesn't change)
const volatile int ip; // a constant integer whose value will never be cached by the system
They each have their own purposes. Any C++ textbook or half decent resource will have explanations of each.
I was reading about volatile member function and came across an affirmation that member function can be both const and volatile together. I didn't get the real use of such a thing. Can anyone please share their experience on practical usage of having member function as const and volatile together.
I wrote small class to test the same:
class Temp
{
public:
Temp(int x) : X(x)
{
}
int getX() const volatile
{
return X;
}
int getBiggerX()
{
return X + 10;
}
private:
int X;
};
void test( const volatile Temp& aTemp)
{
int x = aTemp.getX();
}
int main(int argc, char* argv[])
{
const volatile Temp aTemp(10);
test(aTemp);
return 0;
}
The cv qualification distilled means:
I won't change the value, but there is something out there that can.
You are making a promise to yourself that you won't change the value (const qualification) and requesting the compiler to keep its slimy hands off of this object and turn off all optimization (volatile qualification). Unfortunately, there is little standard among the compiler vendors when it comes to treating volatile fairly. And volatile is a hint to the compiler after all.
A practical use case of this is a system clock. Supposing 0xDEADBEEF was your system specific address of a hardware clock register you'd write:
int const volatile *c = reinterpret_cast<int *>(0xDEADBEEF);
You can't modify that register value, but each time you read it, it is likely to have a different value.
Also, can use this to model UARTs.
You asked for a practical example of volatile member functions. Well i can't think of one because the only situations i could imagine are so low-level that i would not consider using a member function in the first place, but just a plain struct with data-members accessed by a volatile reference.
However, let's put a const volatile function into it just for the sake of answering the question. Assume you have a port with address 0x378h that contains 2 integers, 4 bytes each. Then you could write
struct ints {
int first;
int second;
int getfirst() const volatile {
return first;
}
int getsecond() const volatile {
return second;
}
// note that you could also overload on volatile-ness, just like
// with const-ness
};
// could also be mapped by the linker.
ints const volatile &p = *reinterpret_cast<ints*>(0x378L);
You are stating
I'm not changing them, but another thing outside this abstract semantics could change it. So always do a real load from its address.
Actually, volatile signals that the value of an object might not be the value last stored into it but is actually unknown and might have been changed in between by external (not observable by the compiler) conditions. So when you read from a volatile object, the compiler has to emulate the exact abstract semantics, and perform no optimizations:
a = 4;
a *= 2;
// can't be optimized to a = 8; if a is volatile because the abstract
// semantics described by the language contain two assignments and one load.
The following already determines what volatile does. Everything can be found in 1.9 of the Standard. The parameters it talks about are implementation defined things, like the sizeof of some type.
The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below. [...]
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible execution sequences of the corresponding instance of the abstract machine with the same program and the same input. [...]
The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.
I've never needed anything being both const and volatile, but here's my guess:
Const: You, your code, is not allowed to change the value.
Volatile: The value may change over time without your program doing anything.
So some read-only data exposed by another process or by some hardware would be const and volatile. It could even be memory-mapped into your process and the page marked read-only, so you'd get an access violation if you tried to write to it if it wasn't const.
I think that the reason we have "const volatile" functions is the same as the reason we have "protected" inheritance: The grammar allows it , so we had better think up a meaning for it.
One situation I can think of that could require both const and volatile on a member function would be in an embedded systems situation where you had a the function was logically const but actually had to modify a data cache in a shared memory location (e.g. building a bitmap on demand and caching the bitmap in case the same bitmap was needed again soon). It certainly does not come up very often.
An object marked as const volatile will not be allowed to change by the code where it is declared. The error will be raised due to the const qualifier. The volatile part of the qualifier means that the compiler cannot optimize the code with respect to the object.
In an embedded system this is typically used to access hardware registers that can be read and are updated by the hardware, so it makes no sense to be able to write to the register via the code. An example might be the status register of a serial port.Various bits will indicate a status like if a character is waiting to be read. Each read to this status register could result in a different value depending on what else has occurred in the serial port hardware. It makes no sense to write to the status register but you need to make sure that each read of the register results in an actual read of the hardware.
Below is an illustration :
//We assume that the below declared pointers
//point to the correct
//hardware addresses
unsigned int const volatile *status_reg;
unsigned char const volatile *recv_reg;
#define CHAR_READ 0x01
int get_next_char()
{
while((*status_reg & CHAR_READ) == 0);
return *recv_reg;
}
Hope this helps.
Regards
Sandipan Karmakar.