Is it safe to delete a nullptr twice in C++?

Viewed 376

I have watched a talk in CPPCon which is back to basic: class layout and the link is this. At 54:20, he said it's undefined bahavior to delete the nullptr twice. As far as I know, C++ standard guarantee deleting a nullptr does nothing but why deleting a nullptr twice is undefined bahavior?

And I was told before that there is no need to check if ptr is null in destructor because deleting a null pointer is valid. But if delete a null pointer twice is undefined, does that mean I still need to check if it's nullptr to prevent double-deleting happen?

This is a transcription of the author from his video:

[...] ignore the standard and then got later problems. A common example I see is it's ok to delete a null pointer, that's fine, but you can't delete it twice without resetting the value to some valid pointer value. If I delete the same pointer twice if it's not null you'll get probably a segfault, if it is null it typically just happens to work, but it's not guaranteed to work and there was actually one compiler in the 1980s where it wouldn't work because when you deleted a pointer a new value was overwritten in the deleted pointer. So again, do follow the standard.

3 Answers

Is it safe to delete a nullptr twice in C++?

Yes (in all standard versions of C++). It is guarnteed to work (by work, I mean it doesn't do anyting).

Deletion has no effects if the argument is a null pointer. The compiler that the presenter describes did not conform to the C++ standard. The described compiler also was from the 80's, so it was made before C++ was standardised. The presenter is wrong in saying that you can't delete the null pointer twice if they are referring to standard C++ which does seem to be implied.

It is true that deletion may indirectly cause the program to behave as if the value of the argument pointer was changed (and by as-if rule that means that they effectively can change the value), but only in case where the pointer was non-null and is thus invalidated by the deletion. In fact, this allowance applies to all pointer objects that had the same value as all of them are thereby invalidated. This is because all ways that could observe the value of an invalid pointer are either undefined or implementation defined behaviour.

According to cppreference on the delete expression:

delete expression

...

For the first (non-array) form, expression must be a pointer to an object type or a class type contextually implicitly convertible to such pointer, and its value must be either null or pointer to a non-array object created by a new-expression, or a pointer to a base subobject of a non-array object created by a new-expression.

...

If expression evaluates to a null pointer value, no destructors are called, and the deallocation function may or may not be called (it's unspecified), but the default deallocation functions are guaranteed to do nothing when passed a null pointer.

Deleting nullptr twice is not undefined behavior.

The standard does not say anywhere that delete x; does not change the value of x. That's the point that Dewhurst is making.

Yes, compilers these days don't change the value of x, but that doesn't mean that they are not allowed to. He's absolutely right that after

int *ip = NULL;
delete ip;

there is no requirement that ip is still a null pointer.

We typically say that deleting a null pointer has no effect, but that's a bit of a simplification. The wording in the standard for deleting null pointers is phrased negatively: "if [the pointer value] is not a null pointer, ...". So there are things that the standard implicitly says won't be done. But those things don't include changing the original pointer value.

And, turning it around,

int *ip = new int;
delete ip;
delete ip;

that second delete could be okay, if the compiler sets ip to NULL as part of the first delete. Of course, while that's allowed, it's not required, so don't rely on that. <g>

Related