29

I know that deleteing a null pointer is a no-op:

In either alternative, if the value of the operand of delete is the null pointer the operation has no effect.
(C++ Standard 5.3.5 [expr.delete] p2)

And also that deleting a void* pointer is undefined behaviour because the destructor can't be called as there are no objects of type void:

In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a sub-object representing a base class of such an object. If not, the behavior is undefined.
(C++ Standard 5.3.5 [expr.delete] p2)

Now, normally I take it that things that are listed first overrule things that are listed later on, but what about null void* pointer as the following?

void* p = 0;
delete p; // UB or well-defined?
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • I would expect a well defined behavior of falling into "deleting a NULL pointer" irrespective of the type. Actual freeing and calling the destructor should ideally follow the check for NULL. – deepsnore May 30 '11 at 04:23
  • On g++ I get a warning `deleting ‘void*’ is undefined`. I think its UB (not 100% sure). – Prasoon Saurav May 30 '11 at 04:25
  • @Prasoon: VS2010 doesn't emit such a warning with `/W4`. Also, I believe g++ doesn't inspect the value of the pointer in that case and just acts on the type? – Xeo May 30 '11 at 04:27
  • 4
    At the max it should be **harmless UB**. :)) – iammilind May 30 '11 at 04:28
  • @Nawaz : No it is not a dupe. This one is specifically targetted to deleting a null `void*`. – Prasoon Saurav May 30 '11 at 04:42
  • @Prasoon: But the link has answer to the question with which I agree. – Nawaz May 30 '11 at 04:44
  • My guess: undefined. Firstly, whether the value of `p` is `0` or not is - in general - only known at run-time. Secondly, lets say for arguments sake that some outer `new`/`delete` implementation chooses between a small-object allocator and a general heap (e.g. C's malloc/free), both of which check for and ignore 0 pointers. The `new`/`delete` implementation has to choose between redundantly checking for 0 or passing 0s through - either choice seems legitimate to me. But where to pass the 0 can only be decided after getting `sizeof` the type to which the pointer refers.... – Tony Delroy May 30 '11 at 04:45
  • 3
    Voted to reopen: the point of the question is when the value of the pointer is NULL. The context is different and the prerequisite of the quote of the standard (which says "if the static type of the object doesn't match the dynamic type and there isn't a virtual destructor, UB") isn't met (there is no object so considering the static and dynamic type doesn't make sense) and we can rely on the earlier mention that a null pointer is a valid argument. So my answer is: this is not an UB. – AProgrammer May 30 '11 at 13:39
  • Why `delete`ing a pointer to any **incomplete** type has ever been allowed in C++ is a mystery. – curiousguy Sep 30 '11 at 01:06
  • This is such a pedantic question. It's great to understand the principle, but I can't see the use of it. – bobobobo May 07 '13 at 00:57

3 Answers3

13

I wonder how you can reach up a situation where you are deleting a pointer only if it is null. But staying in language lawyering mode...

In C++ 03

5.3.5/1

the operand of delete shall have a pointer type or a class type having a single conversion to a pointer type.

void* is a pointer type so a null void pointer meets the static requirement.

5.3.5/2

In either alternative [delete and delete[]], if the value of the operand of delete is the null pointer the operation has no effect.

And this gives the wanted behavior.

5.3.5/3

In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behavior is undefined.

This is not relevant, a null pointer doesn't reference an object on which to check the additional constraint.

In C++ 0X

5.3.5/1

The operand shall have a pointer to object type, or a class type having a single non-explicit conversion function (12.3.2) to a pointer to object type.

void* isn't a pointer to object type, so should be rejected.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • 1
    It is interesting to know this won't work in C++0x anymore. :) – Xeo May 30 '11 at 14:18
  • Also, note, your assuming at the top isn't quite correct: I only end up deleting a null `void*` pointer conditionally if I wanted to. ;) In any other situation, I'll delete a valid object. – Xeo May 30 '11 at 14:34
  • Something like [this](http://ideone.com/zQLAQ). See the default constructor, I don't want to check for a valid `_delete` function pointer, and I knew `delete`ing `0` is a no-op, now the only question was: on what should I parameterize the `erased_delete` function? :) – Xeo May 30 '11 at 14:42
  • Specialize erased_delete on void so that it is a noop. It won't be a UB if someone pass you a non null void* and will compile in the future C++0X. (BTW, I assume you left out the assignment operator just to make it simple here) – AProgrammer May 30 '11 at 14:47
  • That `erased_delete` isn't used in my final implementation, I simply cast it to an `int*`. :) But specializing on `void` might be a good idea anyways, so I can `static_assert` inside of it. – Xeo May 30 '11 at 14:56
8

§5.3.5/3 says,

In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined73

In the footnote it says,

73 - This implies that an object cannot be deleted using a pointer of type void* because there are no objects of type void.

So yeah, its UB.

Now once it enters into the city of undefined behaviour, it doesn't matter whether its null or not, since its behaviour cannot remain well-defined precisely for the reason that it already got a residence in the city of undefined behavior.


EDIT:

Got another topic which also quotes the same and says its UB:

Is it safe to delete a void pointer?

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 1
    +1, good link and references; but we should also keep in mind that pointer is 0, so will it harm ? – iammilind May 30 '11 at 04:42
  • 1
    @Nawaz: Your post is just a duplicate of [Neil Butterworth's post here](http://stackoverflow.com/questions/941832/is-it-safe-to-delete-a-void-pointer/941959#941959). – Prasoon Saurav May 30 '11 at 04:44
  • 2
    @Nawaz : I don't see the relevance of **your post** then. :-) – Prasoon Saurav May 30 '11 at 04:46
  • @Prasoon: Actually first I quoted the reference, and then I got the link. That is why I voted for closing the topic, as in my opinion, the link has answer to this question. What relevance you're talking about? – Nawaz May 30 '11 at 04:47
  • @Nawaz : I am talking about the relevance of your post after you got the link. Its *just a copy*. – Prasoon Saurav May 30 '11 at 04:51
  • @Prasoon: Oh by the way, my post is not an exact "same" either. Just see the superscript "73" at the end of the first quote. Its an exact "copy" of the Standard. :D – Nawaz May 30 '11 at 04:58
  • @iammilind: You said : `but we should also keep in mind that pointer is 0, so will it harm ?`. I added an explanation. see my answer again. – Nawaz May 30 '11 at 05:13
  • 1
    @iammilind: the problem is that once you have undefined behavior, the compiler can do crazy things. As such the nullity of the argument is not relevant, since it does not necessarily results in a runtime check anyway. Read Chris Lattner's excellent serie on the LLVM blog for some Undefined Behavior in C to see what compilers do :) – Matthieu M. May 30 '11 at 06:51
  • 2
    There is no object here, that quote is irrelevant. – AProgrammer May 30 '11 at 13:43
  • @AProgrammer: The term object refers to the object in the syntax `delete object`. Or what would you call `p` in `delete p` in a more general sense? – Nawaz May 30 '11 at 13:51
  • 1
    @Nawaz, the object obviously refer to the object pointed by the deleted pointer (considering the dynamic type would not make sense if it isn't the case). And considering the dynamic type of the result of dereferencing a null pointer doesn't make sense. (Note also that in C++0X, the language is different and it seems to me that delete of a void* should be statically rejected). – AProgrammer May 30 '11 at 14:01
  • @AProgrammer: Where this C++0x came from all of sudden? Are we discussing C++0x or C++03? – Nawaz May 30 '11 at 14:08
  • @Nawaz, C++0X wasn't mentioned before. I mentioned it after seeing that the language in the standard changed enough that there deleting a void* is statically forbidden. – AProgrammer May 30 '11 at 14:14
  • @AProgrammer: That is good. But I didn't get how the quote is irrelevant (considering C++03)? – Nawaz May 30 '11 at 14:18
  • 1
    The quote says "if the pointed object has the property that 1/ its static type is different of its dynamic type, 2/ there isn't a virtual destructor in its static type, there is an UB". There is no pointed object, so there is no UB by this rule. – AProgrammer May 30 '11 at 14:23
2

I believe its undefined behaviour. new void isn't allowed (you are not allowed to create objects of type void) so calling delete on a void* should not make sense either. It doesn't matter if it is pointing to NULL or not. I would never use such thing anywhere in my code.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 3
    I won't use it too, it just came to mind with certain circumstances involving a templated deleter function, a function pointer to such a function and a default value for my `void*`. :) – Xeo May 30 '11 at 04:55