Is it good practice to NULL a pointer after deleti

2018-12-31 19:11发布

I'll start out by saying, use smart pointers and you'll never have to worry about this.

What are the problems with the following code?

Foo * p = new Foo;
// (use p)
delete p;
p = NULL;

This was sparked by an answer and comments to another question. One comment from Neil Butterworth generated a few upvotes:

Setting pointers to NULL following delete is not universal good practice in C++. There are times when it is a good thing to do, and times when it is pointless and can hide errors.

There are plenty of circumstances where it wouldn't help. But in my experience, it can't hurt. Somebody enlighten me.

18条回答
与君花间醉酒
2楼-- · 2018-12-31 19:11

Firstly, there are a lot of existing questions on this and closely related topics, for example Why doesn't delete set the pointer to NULL?.

In your code, the issue what goes on in (use p). For example, if somewhere you have code like this:

Foo * p2 = p;

then setting p to NULL accomplishes very little, as you still have the pointer p2 to worry about.

This is not to say that setting a pointer to NULL is always pointless. For example, if p were a member variable pointing to a resource who's lifetime was not exactly the same as the class containing p, then setting p to NULL could be a useful way of indicating the presence or absence of the resource.

查看更多
栀子花@的思念
3楼-- · 2018-12-31 19:11

I'll change your question slightly:

Would you use an uninitialized pointer? You know, one that you didn't set to NULL or allocate the memory it points to?

There are two scenarios where setting the pointer to NULL can be skipped:

  • the pointer variable goes out of scope immediately
  • you have overloaded the semantic of the pointer and are using its value not only as a memory pointer, but also as a key or raw value. this approach however suffers from other problems.

Meanwhile, arguing that setting the pointer to NULL might hide errors to me sounds like arguing that you shouldn't fix a bug because the fix might hide another bug. The only bugs that might show if the pointer is not set to NULL would be the ones that try to use the pointer. But setting it to NULL would actually cause exactly the same bug as would show if you use it with freed memory, wouldn't it?

查看更多
怪性笑人.
4楼-- · 2018-12-31 19:12

There is always Dangling Pointers to worry about.

查看更多
不再属于我。
5楼-- · 2018-12-31 19:13

In a well structured program with appropriate error checking, there is no reason not to assign it null. 0 stands alone as a universally recognized invalid value in this context. Fail hard and Fail soon.

Many of the arguments against assigning 0 suggest that it could hide a bug or complicate control flow. Fundamentally, that is either an upstream error (not your fault (sorry for the bad pun)) or another error on the programmer's behalf -- perhaps even an indication that program flow has grown too complex.

If the programmer wants to introduce the use of a pointer which may be null as a special value and write all the necessary dodging around that, that's a complication they have deliberately introduced. The better the quarantine, the sooner you find cases of misuse, and the less they are able to spread into other programs.

Well structured programs may be designed using C++ features to avoid these cases. You can use references, or you can just say "passing/using null or invalid arguments is an error" -- an approach which is equally applicable to containers, such as smart pointers. Increasing consistent and correct behavior forbids these bugs from getting far.

From there, you have only a very limited scope and context where a null pointer may exist (or is permitted).

The same may be applied to pointers which are not const. Following the value of a pointer is trivial because its scope is so small, and improper use is checked and well defined. If your toolset and engineers cannot follow the program following a quick read or there is inappropriate error checking or inconsistent/lenient program flow, you have other, bigger problems.

Finally, your compiler and environment likely has some guards for the times when you would like to introduce errors (scribbling), detect accesses to freed memory, and catch other related UB. You can also introduce similar diagnostics into your programs, often without affecting existing programs.

查看更多
查无此人
6楼-- · 2018-12-31 19:13

I can imagine setting a pointer to NULL after deleting it being useful in rare cases where there is a legitimate scenario of reusing it in a single function (or object). Otherwise it makes no sense - a pointer needs to point to something meaningful as long as it exists - period.

查看更多
零度萤火
7楼-- · 2018-12-31 19:17

As others have said, delete ptr; ptr = 0; is not going to cause demons to fly out of your nose. However, it does encourage the usage of ptr as a flag of sorts. The code becomes littered with delete and setting the pointer to NULL. The next step is to scatter if (arg == NULL) return; through your code to protect against the accidental usage of a NULL pointer. The problem occurs once the checks against NULL become your primary means of checking for the state of an object or program.

I'm sure that there is a code smell about using a pointer as a flag somewhere but I haven't found one.

查看更多
登录 后发表回答