2

When I write a code like this, it prints "not deleted". How can I 100% sure whether a pointer is deleted or not?

int* a = new int;
*a = 5;
delete a;

if (!a)                      //I also tried a == NULL but got same result     
    cout<<"deleted"<<endl;
else
    cout<<"not deleted"<<endl;
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
ibrahim
  • 3,254
  • 7
  • 42
  • 56
  • You can set `a` to null after deletion to signify it's now invalid, although rarely you need to do so. – Pubby Dec 27 '11 at 22:31

7 Answers7

4

You can't. Make sure to get rid of all copies of a pointer when you delete it, as the memory location referenced by the pointer will probably get reused later for different data.

  • 1
    First useful answer I've seen to a question like this. If you don't get rid of the copies, some implementations of C++ will try to `delete` the pointer again upon program exit. – Trevor Jex Jun 11 '18 at 03:33
3

calling delete on a pointer does not set the pointer itself to NULL (why should it? You will realize that it couldn't possibly do so given the signature of delete, i.e., it takes a void* not a void**).

Why do you (think that you) need this? You shouldn't need to detect this situation, just structure your code such that the memory is freed deterministically.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • More importantly, it doesn't change any aliases. – Joel Dec 27 '11 at 22:30
  • I need to check a node of tree that I am implementing for my hw, is deleted or not? – ibrahim Dec 27 '11 at 22:34
  • @ibrahim: You shouldn't need to. When you remove/delete a node from the tree then the surrounding nodes should be modified to connect to each other in its place. You can of course explicitly set it to NULL, but I don't see why you would need to. – Ed S. Dec 27 '11 at 22:36
  • 1
    "You will realize that it couldn't possibly do so" - that doesn't follow, because `delete` is an operator. Operators of course can modify their operands. Stroustrup states in his C++ FAQ that `delete` *is* allowed to set lvalue operands to zero, although I don't see anything in the standard to support his claim. Maybe it's a pre-standard thing. – Steve Jessop Dec 27 '11 at 23:04
  • @SteveJessop could you please provide a link for a mentioned Stroustrup's FAQ item? – Ivan Aksamentov - Drop Aug 15 '15 at 17:58
2

You don't "delete" a pointer, you delete what the pointer addresses.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
1

Arrange your code like this:

{
    int* a = new int;
    *a = 5;
    delete a;
}
// a no longer exists so you know it is gone.

PS. Prefer never to use RAW pointers.

{
   // C++03
   std::auto_ptr<int> a(new int);
   *a = 5;
}

Or

{
   // C++11
   std::unique_ptr<int> a(new int);
   *a = 5;
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
0

Deleting the pointer won't set it to NULL, it deletes the memory pointed to by the pointer. Even if you were to examine the memory you won't be able to make out whether it's free or not. In other words checking whether a pointer is pointing to "available" memory or not is not simple, certainly not as simple as a == NULL.

That's why it's considered a good practice to set the pointer to NULL as soon as you free the memory it's pointing to:

int* a = new int;
*a = 5;
delete a;
a = NULL;

if (!a)                      //I also tried a == NULL but got same result     
    cout<<"deleted"<<endl;
else
    cout<<"not deleted"<<endl;
Kashyap
  • 15,354
  • 13
  • 64
  • 103
  • 4
    Doing that hides other errors in the code. Best not to do it and find these errors during testing. – Martin York Dec 27 '11 at 22:35
  • @LokiAstari For example..... ? – Kashyap Dec 27 '11 at 22:36
  • There are still problems with this "strategy". The most basic one is making a copy of `a` (`int* b = a`) then deleteing `a`. `b` still holds the same address but now it is invalid and hasn't been set to NULL and the OP will still encounter the same problems when testing against `b`. But this of course is a contrived example. – Marlon Dec 27 '11 at 22:38
  • The problem is it provides no real benefit. Yet it hides other types of error that can potentially be fixed. Thus it is best not to do this. The best strategy is not to fall into this situation and let your pointers fall out of scope once they have been deleted. – Martin York Dec 27 '11 at 22:47
  • 'set the pointer to NULL as soon as you free the memory it's pointing to:'.. unless you are immediately overwriting it with another valid pointer or, probably, other reasons to not set it to null. – Martin James Dec 28 '11 at 00:05
  • @LokiAstari coding such that pointers fall out of scope at end of use is tougher done than said. Variable reuse (for lack of a better word) is one of the basic use of a pointer IMHO. – Kashyap Feb 27 '12 at 18:12
  • @thekashyap: If you are writing C maybe (but I doubt it). In C++ it is standard and I would never re-use a variable. That is why we have compilers. – Martin York Feb 27 '12 at 19:02
0

Why not use valgrind to "prove" experimentally that the application has no memory leaks - proving that all nodes have been removed and their contents deleted?

Valgrind runs the application in a virtual machine and keeps track or all allocations and de-allocations on the heap. It's report any invalid memory accesses and can be configured to report how many memory leaks there are (manually allocated memory that isn't deallocated).

0

The simple fact is this: C++ is not a safe language.

And that's good. If you're using C++, you want to control when you have safety, how you have it, and where you want to be unsafe.

When you manually delete a pointer, there is absolutely no indication anywhere that the pointer has been deleted. This is why most modern C++ texts will tell you that, unless you have some specific reason otherwise, do not use naked pointers. You should not be manually deleting pointers at all, unless again you have some specific reason to do so.

If you're making a data structure, then it's up to you how safe you want this data structure to be. Note that C++ standard library data structures allow for iterators (generalized pointers) to become invalid under certain conditions. This puts the responsibility on the user to know what they're doing.

The gain for this is fast performance. If you don't want that performance, then you need to use a safer container or data structure. If you want that safety, then you should use a smart pointer for elements in your data structure. The user should get shared_ptr<> or weak_ptr<> objects that reference nodes rather than naked pointers. And so forth.

C++ isn't safe. Of course it isn't safe; it's C++. But it's good.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982