Why doesn't delete set the pointer to NULL?
Asked Answered
S

13

150

I always wondered why automatic setting of the pointer to NULL after delete is not part of the standard. If this gets taken care of then many of the crashes due to an invalid pointer would not occur. But having said that I can think of couple of reasons why the standard would have restricted this:

  1. Performance:

    An additional instruction could slow down the delete performance.

  2. Could it be because of const pointers.

    Then again standard could have done something for this special case I guess.

Does anyone know exact reasons for not allowing this?

Substation answered 1/4, 2009 at 7:48 Comment(0)
M
172

Stroustrup himself answers. An excerpt:

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.

But the main issue he raises is that delete's argument need not be an lvalue.

Metal answered 1/4, 2009 at 8:23 Comment(2)
I think this could use some more explanation. I'm not even sure what he's saying...I suppose I'll have to come back at a later time when I can dedicate a couple hrs to researching this until I get it. Or, you could expound upon the answer to help us understand more quickly.Single
It would be nice if the standard delete overloaded for lvalue & rvalue, so it would set the argument to nullptr when it is an lvalue.Entertaining
R
74

First, setting to null would require a memory stored variable. It's true, that you usually have a pointer in a variable but sometimes you might want to delete an object at a just calculated address. That would be impossible with "nullifying" delete.

Then comes performance. You might have written code in such a way that the pointer will go out of scope immediately after delete is done. Filling it with null is just a waste of time. And C++ is a language with "don't need it? then you don't have to pay for it" ideology.

If you need safety there's a wide range of smart pointers at you service or you can write your own - better and smarter.

Reggy answered 1/4, 2009 at 7:56 Comment(3)
Good point wrt calculated address, even if it's something you don't see oftenSabinesabino
are you talking about placement new when you say that sometimes you might want to delete an object at a just calculated address. ???Caboose
@PravasiMeet No, I mean something like delete (ptr + i)Reggy
P
45

You can have multiple pointers pointing to that memory. It would create a false sense of security if the pointer you specified for the delete got set to null, but all the other pointers did not. A pointer is nothing more than an address, a number. It might as well be an int with a dereference operation. My point is you would have to also scan every single pointer to find those that are referencing the same memory you just deleted, and null them out as well. It would be computationally intense to scan all the pointers for that address and null them out, because the language is not designed for that. (Although some other languages structure their references to accomplish a similar goal in a different way.)

Paviour answered 1/4, 2009 at 7:58 Comment(0)
G
22

A pointer can be saved in more than one variable, setting one of these to NULL would still leave invalid pointers in the other variables. So you don't really gain much, you are more likely creating a false sense of security.

Besides of that, you can create your own function that does what you want:

template<typename T>
void deleten(T *&ptr) {
  delete ptr;
  ptr = NULL;
}
Guaiacum answered 1/4, 2009 at 8:0 Comment(2)
Using your logic, what do I gain from creating a delete function wrapper? Now if the only problem is this false positive, I dont think we have a problem. For one, code built to share memory shouldn't be using nullpointer check too verify if the have valid memory. They should be checking a reference count.Retrorse
also to add delete is not necessarily limited to lvalues. i.e delete func(); is validKlagenfurt
S
12

Because there isn't really any need to, and because it would require delete taking pointer-to-pointer rather than just pointer.

Sabinesabino answered 1/4, 2009 at 7:50 Comment(2)
true, but that would result in the same overheadSabinesabino
There isnt a need to? hmm... Well I guess we also dont need to check if a pointer is NULL.Retrorse
C
9

delete is used mostly in destructors, in which case setting a member to NULL is pointless. A few lines later, at the closing }, the member no longer exists. In assignment operators, a delete is typically followed by an assignment anyway.

Also, it would render the following code illegal:

T* const foo = new T;
delete foo;
Creole answered 2/4, 2009 at 8:25 Comment(1)
No it wouldn't. C++ abstract machine can do whatever it pleases. ie design rules that allows the compiler to do this. As an example, Type punning aka type casting is undefined behaviour in C. but if you use memcpy the Cpp abstract machine (supposedly) does a type cast for you in the background.Retrorse
C
6

Here's another reason; suppose delete does set its argument to NULL:

int *foo = new int;
int *bar = foo;
delete foo;

Should bar get set to NULL? Can you generalize this?

Crude answered 1/10, 2010 at 3:22 Comment(0)
S
5

If you have an array of pointers, and your second action is to delete the empty array, then there is no point setting each value to null when the memory is about to be freed. If you want it to be null.. write null to it :)

Siberson answered 1/4, 2009 at 7:52 Comment(0)
B
4

C++ allows you to define your own operator new and delete so that for instance they would use your own pool allocator. If you do this then it is possible to use new and delete with things that are not strictly addresses but say indexes in your pool array. In this context the value of NULL (0) might have a legal meaning (referring to the first item in the pool).
So having delete set NULL automatically to its argument doesn't always have the meaning of - set the value to an invalid value. The invalid value may not always be NULL.

Buckling answered 1/4, 2009 at 8:9 Comment(0)
M
4

Philosophy of C++ is "pay for it only if you use it". I think it may answer your question.

Also sometimes you could have your own heap which will recover deleted memory.. or sometimes pointer not owned by any variable. Or pointer stored in few variables - it possible zero just one of them.
As you can see it have many issues and possible problems.

Miss answered 1/4, 2009 at 8:26 Comment(0)
C
3

Setting the pointer to NULL automatically would not solve most of the issues with bad pointer usage. The only crash it would avoid is if you try to delete it twice. What if you call a member function on such a pointer? It would still crash (assuming that it accesses member variables). C++ does not restrict you from calling any function on NULL pointers, nor should it do that from performance point of view.

Card answered 1/4, 2009 at 8:18 Comment(2)
I think the feature would violate pay if you use policy. And deleting 1 million objects such as 1 million std::string(s) could run 3 million/6 million useless operations. This is a reason why global variables get initialized; while local variables are not. Since local variables will be constantly created and initialized for the remainder of your program.Retrorse
However, I wonder if cpp could mandate that delete also zeros out pointers; BUT!!! use optimization tricks to actually not zero out the value, EVERYTIME. Such as when the pointer goes out of scope before being written to again. This logic could also work for local variables. primitive local variables will be guaranteed initialized to zero. But so long as they are explicitly initialized before use, They are not actually initialized in assembly code.Retrorse
R
0

Well I saw 12 answers, and 11 gave cons to the idea. Nimesh Bapodra' answer was the only one pro to the idea.

After reading all the answers and comments and put thought into it; I am 100% for the idea! Lets recap the reasons against the idea.

  • Don't pay for what you don't use
  • False positives if multiple pointers share memory
  • Setting the values of const/temporary pointers
  • C++ allows overload of operator delete
  • It is not necessary

It is not necessary
Well I guess checking if a pointer is not null is also unnessary? Garbage collectors in Java/C# is unnecessary. Like what is the sense in the compiler helping us to keep our code safe? Might as well remove const keyword while we are at it. That is too much typing.

C++ allows overload of operator delete
Well guess what? The built in version can keep us safe. And your version can do whatever it likes.

False positives if...
False positives if multiple pointer shared the same memory. At first it seems to make sense; but when you think couple steps further you see it absolutely makes no sense. What false positive? If you are sharing memory across pointers, you shouldn't be relying on nullpointer checks to determine if the memory is valid. You should be checking a reference counter. If, just if, your logic wants to depend on nullpointer checks; you would have to IMMEDIATELY set to NULL everyother pointer! else your darn state machine would be in an invalid mess... ANYHOW!!!! Furthermore, who is going to waste cpu cycles to set all those pointers NULL?

Setting the value of const pointers
This seems reasonable. But only if you are a novice to programming. The C++ abstract machine is allowed to do anything it wishes. It has god like powers in its realm. It is master and we are the servants. It can decide to discard UB code. It can decide to give UB code a bly in life. There is nothing stopping the compiler from modifying const pointers. const pointers are nothing more than pointers with a const attribute. You can remove that with a const_cast. The compiler could do it without a sweat.

Don't pay for what you don't use
This is the major concern for most people. But there is a simple fool proof work around. 1. Guarantee that all pointers will become NULL when deleted(built in version). 2. Break the guarantee aka optimize, if nulling the pointer is not necessary. Such as no more access to pointer before it looses scope. That one is easy to implement. Any deleted pointer still in scope being accessed is UB anyhow(except for equality operators, I assume). And on the same note, I think Cpp should guarantee that local variables be initialized to zero. But then optimize the code to not initialize local variables which were explicitly initialized before use.

But here is the catch... As I put in this long work putting this together and thinking about it; I came up with two problems no bother mentioned. Worst yet, I have no solution for one of them.(Or so I thought).

Would break backward compatibility
Someone with a const pointer, I dont know how much of you exist, will suffacate if his const pointer to memory is all of a sudden NULL. Let's say he intended to exit this function and use said pointer to remove it from a reference count map. Well I think code that rely on deleted address should BREAK. Either you manually save the address in another variable before deleting or you just update the reference count map in this function before deleting the pointer. I really think a safety feature like this is more important.

Setting the value of temporary pointers
At the get go, my simple answer was, well in this case, Cpp doesnt have to nullify anything. Then I thought about what the expression delete (pointer+1) mean.

char **pointer = new pointer*[4];
delete (pointer+1);

In a world where the Cpp abstract machine nullify deleted pointers, one can easily be tricked into thinking that pointer[1] == NULL. And they would be DARN RIGHT. Cpp abstract machine can look at this code and see that pointer is not a temporary, and we to delete the next element of the array. And simply just nullyfy pointer[1]. But check out this next example.

class String
{
 char *begin = new char[1024];
 char *end = s.begin + 1024;

 public: char* getBegin() { return begin; }
};

String s;
delete[] getBegin();

What to do now? Well I think that by encapsulating String::begin into a function, you have encapsulated it; and have no ability to modify it. If you returned a reference, or a pointer to a pointer, then the delete operator could dereference it and nullify the target.

In Summary
I am 100% in agreement with Cpp delete operators(built in) nullifying pointers. It will make Cpp a safer place. I also recommend that Cpp initialize primitive local variables.

Retrorse answered 14/9, 2023 at 3:5 Comment(4)
how exactly does this answer this particular question?Enforce
From Why doesn’t delete null out its operand? - Consider this yet-another reason to minimize explicit use of new and delete by relying on standard library smart pointers, containers, handles, etc.Cryohydrate
@starball The question ask why it doesn't do something. And my answer shows that they have no reason. Furthermore, I think your thinking is narrow. I have provided excellent reason to allow this feature; which is beneficial to every cpp user.Retrorse
@Cryohydrate that is not a fair remark. 1. I should have the right to use any Cpp feature I please; so long as I am not writing code for you. 2. I might not yet understand smart pointers, or might never be able to understand smart pointers, I might never care to use smart pointers. 3. Using pointers is alot more simpler than using encapsulations of STL. 4. This idea of cpp abstract machine ensuring that deleted pointers are NULL would give us one less reason to need smart pointers in the first place. PS. I love using raw pointers.Retrorse
P
-3

I see people giving weird answers to this question.

ptr = NULL; How can such a simple statement cause performance delay?

Another answer is saying that we can have multiple pointers pointing to the same memory location. Surely we can. In this case delete operation on one pointer would make only that pointer NULL (if delete was making pointer NULL) and the other pointer would be non-NULL and pointing to memory location which is free.

The solution for this should have been that user should delete all pointers pointing to same location. Internally it should check if memory is already freed than don't free. Only make the pointer NULL.

Stroustrup could have designed delete to work in this manner. He thought programmers would take care of this. So he ignored.

Prolonge answered 5/4, 2016 at 5:36 Comment(1)
Cpp says dont pay for what you dont use; and in the case of an object that gets destroyed; it is not necessary to set its data fields to valid value.Retrorse

© 2022 - 2024 — McMap. All rights reserved.