10

I am wondering what will hapen if I try to do a delete on a pointer that is already deleted, or may have not been allocated ? I've read two things : first, that delete operator will do some checkings and we do not need to check if the pointer is null ; and then, I read that it can lead to unknown behaviors..

I'm asking it, because I use some personal objects that contains Qt objects attributes ; I think that Qt delete all widgets associated when we close the window, but I'm not pretty sure and still : if the soft crash before the window's close, we have to delete all objects manually.

So, what would be the best solution ? Something like that ?

if( my_object )
    delete my_object;

Can it avoid dangerous behaviours ?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Jérémy Dutheil
  • 6,099
  • 7
  • 37
  • 52

6 Answers6

20

delete on an already deleted non-null pointer is undefined behavior - your program will likely crash. You can safely use delete on a null pointer - it will yield a no-op.

So the real problem is not delete on a null pointer. The real problem is here:

 ptr = new Something();
 otherPtr = ptr;
 delete ptr;
 delete otherPtr;

This can happen if you have several pointers to the same object and it is quite dangerous. The possible solutions are:

  • use smart pointers (no delete in your code) or
  • only have one designated pointer for controlling each object lifetime and delete at exactly the right time.
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 7
    "likely crash" is an understatement, UB could make a raptor jump through your window and make the universe implode. – Filip Roséen - refp Dec 14 '11 at 09:02
  • @refp: I know, but newbies usually don't believe that. – sharptooth Dec 14 '11 at 09:03
  • Your answer is misleading, are you saying delete sets a pointer to 0? It doesn't. `delete ptr;delete ptr;` is just as dangerous. – Joe McGrath Dec 14 '11 at 09:06
  • @Joe McGrath: No, I'm not saying that. The problem with `delete ptr; delete ptr;` is that people reject it as "stupid, noone does that". – sharptooth Dec 14 '11 at 09:16
  • @sharptooth I'm not sure about the "likely crash". At least one implementation I've used, the second delete would be a no-op. Unless the memory had already be reallocated, in which case the new owner is in for a bit of a surprise:-). As we all know, the most frequent "behavior" in the case of undefined behavior is for the program to work perfectly with all of your tests, then crash in the demo in front of the important client. – James Kanze Dec 14 '11 at 10:11
  • Exactly. The worst scenario with undefined behavior is not crashing or imploding the universe, it's when it's pretending to work well. I'd say just crashing is your best-case scenario. – Ludwik Jul 01 '14 at 13:41
4
if( my_object )
    delete my_object;

is redundant. delete on a NULL pointer does nothing. This is guaranteed by the standard.

delete on a pointer that was already deleted causes undefined behavior. That's why you should always remember to assign your pointers to NULL after you delete them:

delete p;
p = NULL;

EDIT: As per the comments, I feel I should specify this. If you have multiple pointers to the same object, the assignment to NULL won't make the delete safe. Regardless, it's better to use smart pointers.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 1
    I disagree with the advice. For one thing, it will likely make the problem much worse because you will get in the habit of thinking that if you have a pointer with a non-NULL value, it's safe to `delete` it, which it certainly is not. (See sharptooth's answer for an example.) – David Schwartz Dec 14 '11 at 09:06
  • 1
    That will only silence the error. Let it crash so you can get rid of the double-delete/be reminded to use smart pointers. – GManNickG Dec 14 '11 at 09:07
  • There is an explanation [here](http://stackoverflow.com/questions/33374483/what-does-visual-studio-do-with-a-deleted-pointer-and-why?rq=1) of what is the value that is set to the pointer after the deletion of an object. – fyts Jul 27 '16 at 10:04
1

Please note that deleting a pointer does not set it to NULL.

int* i = new int;
*i = 42;
delete i;
delete i; // oops! i is still pointing to the same memory, but it has been deleted already

Deleting a null pointer doesn't do anything, deleting an already deleted object will result in undefined behaviour.

Jan
  • 1,807
  • 13
  • 26
1

the right way is:

if( my_object )
{
    delete my_object;
    my_object = NULL;
}

because, calling twice the way it was before will call delete on a deleted pointer.

Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94
0

It results in Undefined Behavior if you call delete on already deleted pointer.
Calling delete on a NULL pointer has no-effect though.

Standard c++03 § 3.7.4.2-3

If a deallocation function terminates by throwing an exception, the behavior is undefined. The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_-t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](std::size_t) or operator new[](std::size_t, const std::nothrow_t&) in the standard library.

Using RAII & Smart Pointers are your best weapons to avoid such problems.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
0

Just to combine the answers above:

  • if (my_object) checks the value of the pointer, not the existence of the object. If it is already deleted, the pointer may still point to that location.
  • deleting an already deleted object is undefined behavior and will probably crash your program.
  • deleting NULL is defined and does nothing. Together with point 1 this explains the answer of Luchian.

To sum it up: You have to be clear on who owns the object and where the different pointer to the object are. When you delete an object, make sure to set all pointer pointing to that location to 0/NULL. Use managing objects like boost::shared_pointer or QPointer to help you in this task.

Tobias Langner
  • 10,634
  • 6
  • 46
  • 76