In an answer, https://stackoverflow.com/a/704568/8157187, there is a quote from Stroustrup:
C++ explicitly allows an implementation of delete to zero out an lvalue operand, and I had hoped that implementations would do that, but that idea doesn't seem to have become popular with implementers.
However, I failed to find this explicit statement in the standard. There is a part of the current draft standard (N4659), that one may interpret this way:
6.7:
When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values (6.9.2). Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have unde?ned behavior. Any other use of an invalid pointer value has implementation-de?ned behavior.
Footnote: Some implementations might de?ne that copying an invalid pointer value causes a system-generated runtime fault
So, after a delete ptr;
, ptr
's value becomes a invalid pointer value, and using this value has implementation-defined behavior. However, it doesn't say that ptr
's value is allowed to change.
It might be a philosophical question, how can one decide that a value has changed, if one cannot use its value?
6.9:
For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (4.4) making up the object can be copied into an array of char, unsigned char, or std::byte (21.2.1).43 If the content of that array is copied back into the object, the object shall subsequently hold its original value.
So, it seems, that it is valid to memcpy
an invalid pointer value into a char array (depending on which statement is "stronger", 6.7 or 6.9. To me, 6.9 seems stronger).
This way, I can detect, that the pointer value has been changed by delete
: memcpy
the pointer's value before and after the delete
to char array, then compare them.
So, as I understand, 6.7 doesn't grant that delete
is allowed to modify its parameter.
Is delete allowed to modify its parameter?
Check out the comments here: https://stackoverflow.com/a/45142972/8157187
Here's an unlikely, but still possible real-world code, where this matters:
SomeObject *o = ...; // We have a SomeObject
// This SomeObject is registered into someHashtable, with its memory address
// The hashtable interface is C-like, it handles opaque keys (variable length unsigned char arrays)
delete o;
unsigned char key[sizeof(o)];
memcpy(key, &o, sizeof(o)); // Is this line OK? Is its behavior implementation defined?
someHashtable.remove(key, sizeof(key)); // Remove o from the hashtable
Of course, this snippet can be reordered, so it becomes a surely valid code. But the question is: is this a valid code?
Here's a related train of thought: suppose, that an implementation does define what footnote describes:
copying an invalid pointer value causes a system-generated runtime fault
6.9 guarantees that I can memcpy()
any value. Even an invalid one. So in this theoretical implementation, when I memcpy()
the invalid pointer value (which should succeed, 6.9 guarantees that), in a sense, I don't use the invalid pointer value, but only its underlying bytes (because it would generate a runtime fault, and 6.9 doesn't allow it), so 6.7 doesn't apply.