Is “delete p; p = NULL(nullptr);” an antipattern?

前端 未结 7 1423
长发绾君心
长发绾君心 2021-02-05 13:35

Searching something on SO, I stumbled across this question and one of the comments to the most voted answer (the fifth comment to that most voted answer) suggests that del

相关标签:
7条回答
  • 2021-02-05 13:51

    It depends on how the pointer is used. If all the code that can see the pointer should "know" that it's no longer valid — especially in a destructor where the pointer is about to go out of scope anyway — there's no need to set it to null.

    On the other hand, the pointer may represent an object that sometimes exists, sometimes doesn't, and you have code like if (p) { p->doStuff(); } to act upon the object when it exists. In that case, obviously, you should set it to null after deleting the object.

    The important distinction in the latter case is that the lifetime of the pointer variable is much longer than the lifetime of the objects it (sometimes) points to, and its null-ness carries some significant meaning that has to be communicated to other parts of the program.

    0 讨论(0)
  • 2021-02-05 13:57

    The reason is that the extra setting to null will only help in very limited contexts. If you are in a destructor, the pointer itself will not exist right after the destructor execution, which means that whether it is null or not does not matter.

    Got to correct this statement since it is false in C++.

    The other functions of an object being destroyed may be called while the object is getting destroyed (because somehow the destruction process requires it.) It is generally viewed as ugly, but there not always good work around.

    Therefore, clearing your pointers may be the only good solution to avoid problems (i.e. these other functions being called can then test to see whether the object is valid before using it.)

    Yet, a good idea in C++ is to use smart objects (probably what you are talking about). More or less, a class that holds a reference to an object and which makes sure said object is released when the destructor is hit and not add many objects to destroy all at once in one object (although the result is the same, it is cleaner.)

    0 讨论(0)
  • 2021-02-05 13:59

    I recommend doing so.

    • Obviously, it's valid in a context where NULL is a valid value of the pointer. This, of course, means if it's used in other places, it must be checked.
    • Even if the pointer may, technically, not be NULL, it does help in real-world scenarios when customers send you a crash dump. If it's NULL and it's not supposed to be (and it wasn't trapped in testing with the assert() that you should do), then it's easy to see that this is the problem - you'll crash at something like mov eax, [edx+4] or something, you'll see that edx is 0, and you know what the problem is. If, on the other hand, you don't NULL the pointer, but it is deleted, then all sorts of things may happen. It may work, it may crash immediately, it may crash later, it may show weird things - at this point, anything that happens is soft-non-deterministic.
    • Defensive programming is King. That includes setting a pointer to NULL extraneously, even if you think you don't have to, and doing that extra NULL check in a few places even though you technically know it isn't supposed to happen.
    • Even if you have the logic error of a pointer going through delete twice, it's better to not crash and handle it safely than to crash. That may mean you do that extra check, and you'll probably want to log that, or maybe even end the program gracefully, but it's not just a crash. Customers don't like that.

    Personally, I use an inline function that takes the pointer as a reference and sets it to NULL.

    0 讨论(0)
  • 2021-02-05 14:00

    No, it's not an anti-pattern.

    Setting a pointer to NULL is a perfectly good way of indicating that the pointer is no longer pointing at anything valid. In fact, that's exactly what NULL value is intended to mean.

    If there's an anti-pattern to be avoided here, the anti-pattern would be not having a simple and well-defined set of rules/conventions for how your program manages its memory. It doesn't matter so much what those rules are, as long as they work to avoid leaks and crashes, and as long as you can and do follow them consistently.

    0 讨论(0)
  • 2021-02-05 14:03

    Yes, I would not recommended doing it.

    The reason is that the extra setting to null will only help in very limited contexts. If you are in a destructor, the pointer itself will not exist right after the destructor execution, which means that whether it is null or not does not matter.

    If the pointer was copied, setting p to null will not set the rest of the pointers, and you can then hit the same problems with the extra issue that you will be expecting to find deleted pointers being null, and it won't make sense how your pointer became non-zero and yet the object is not there....

    Additionally it might hide other errors, like for example if your application is trying to delete a pointer many times, by setting the pointer to null, the effect is that the second delete will be converted to a no-op, and while the application will not crash the error in the logic is still there (consider that a later edit accesses the pointer right before the delete that is not failing... how can that fail?

    0 讨论(0)
  • 2021-02-05 14:09

    Although I think @Mark Ransom is on sort of the right track, I would suggest there's an even more fundamental problem than just assert(this!=NULL).

    I think it's much more telling that you're using raw pointers and new (directly) often enough to care. While this isn't (necessarily) a code smell/anti-pattern/whatever in itself, it often points toward code that's unnecessarily similar to C, and isn't taking advantage of the things like containers in the standard library.

    Even if the standard containers don't fit your needs well, you can still normally wrap your pointer up into a small enough, simple enough package that techniques like this are irrelevant -- you've restricted access to the pointer in question to such a small amount of code that you can glance through it and assure that it's only ever used when it's valid. As Hoare said, there are two ways of doing things: one is to keep the code so simple there are obviously no deficiencies; the other is to make the code so complex there are no obvious deficiencies. This technique only appears relevant (to me) when you're already dealing with the latter case.

    Ultimately, I see the desire to do this at all as basically admitting defeat -- rather than even attempting to assure that the code is correct, you've done the equivalent of setting up a bug-zapper next to a swamp. It reduces the appearance of bugs in a small area by a small percentage, but leaves so many more free to breed that if there's any effect on the total population, it's far too small to measure.

    0 讨论(0)
提交回复
热议问题