tags:

views:

290

answers:

4

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

+2  A: 

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.

Richard Pennington
Well, freeing it grants everyone else access by allowing `new` to return the same memory. So although it might be allowed, it's certainly unsafe if the memory is genuinely volatile.
Potatoswatter
Potatoswatter: Right, but freeing volatile memory implies it was new'd in the first place otherwise it's a bad thing. I'm assuming that the allocated memory is somehow volatile. I suspect it isn't really.
Richard Pennington
A: 

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?

Carl Norum
Error means compilation error if you code it in delete j
Yan Cheng CHEOK
@Yan Cheng CHEOK: yeah, we kind of guessed that. Can you copy/paste the error?
zneak
@Yan, I'm saying there was no compilation error for me. There's not even a warning if I use `-Wall`.
Carl Norum
A: 

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.

zneak
+1  A: 

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;.

Potatoswatter