In an answer, https://mcmap.net/q/23077/-why-doesn-39-t-delete-set-the-pointer-to-null, 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 undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.
Footnote: Some implementations might define 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://mcmap.net/q/426942/-why-compilers-do-not-assign-null-to-pointer-variable-automatically-after-deleting-dynamic-allocated-memory-duplicate
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.
delete p; if (p==someOtherPOinter){}
should be fine – Iberianif (p == nullptr)
is true for this invalid value. – Tubmanp
's value is not necessarily changed. Just the implementation says thatp==nullptr
is true, ifp
has invalid pointer value. This is different, doesn't mean thatp
's value have changed. – Gliwicememcpy
it, I can see thatp
has changed, which is not allowed anywhere in the standard (at least, as I checked it. It is huge, maybe I missed it). – Gliwicedelete
aconst
object. This changed with the 1998 standardization. It's therefore conceivably possible that other things also changed, such as wording about changing the value of an lvalue pointer expression argument. Still this is of no practical utility. Accessing the value of a pointer after its pointee has been destroyed is Undefined Behavior anyway. – Deettadeeyndelete
and then comparing, is not the same as memcopying the pointer before deletion and then copying it back into the pointer. – Bulrushint a = 0; /* test bits of 'a' now */; /* test bits of 'a' now*/
have two different bits each time. – Bulrushdelete()
method with thedelete
operator. Thedelete()
method can do anything it likes with its parameter, to answer your actual question. It is received by value, so changes inside the method do not propagate outside. Thedelete
operator could zero its operand, as suggested by Stroustrup. Thememcpy()
operations are legal, as the variable itself remains in existence and still has an address. Basically unclear what you're asking. – Millisentoperator delete()
function. But this is exactly what is referred to by "the deallocation function" in `[basic.stc.dynamic.deallocation]/4. (The delete operator invokes destructor then calls deallocation function). – Illustriousoperator delete()
function (which is a deallocation function despite its syntax). The expression following the keyworddelete
in the delete expression doesn't have a specific name but it's clear that OP meant to refer to that by "parameter" in the question – Illustriousint a = 0; char b[sizeof(int)]; memcpy(b, &a, sizeof(int)); if (memcmp(b, &a, sizeof(int)) { printf("differ\n"); }
it is possible that "differ" will be printed? That's quite unexpected... – Gliwiceint
are notchar
objects (so the guarantee about objects retaining their value doesn't apply on a byte by byte basis), and as far as I can tell, the standard doesn't actually say that there must be a relation between the result of aliasing one byte of anint
, and the value of theint
. The C++ memory model has various deficiencies, some much greater than this, a lot of it comes down to "it's meant to work normally" – Illustrious