Is it good practice to NULL a pointer after deleting it?

后端 未结 18 825
猫巷女王i
猫巷女王i 2020-11-22 11:28

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?

<         


        
相关标签:
18条回答
  • 2020-11-22 11:53

    I always set a pointer to NULL (now nullptr) after deleting the object(s) it points to.

    1. It can help catch many references to freed memory (assuming your platform faults on a deref of a null pointer).

    2. It won't catch all references to free'd memory if, for example, you have copies of the pointer lying around. But some is better than none.

    3. It will mask a double-delete, but I find those are far less common than accesses to already freed memory.

    4. In many cases the compiler is going to optimize it away. So the argument that it's unnecessary doesn't persuade me.

    5. If you're already using RAII, then there aren't many deletes in your code to begin with, so the argument that the extra assignment causes clutter doesn't persuade me.

    6. It's often convenient, when debugging, to see the null value rather than a stale pointer.

    7. If this still bothers you, use a smart pointer or a reference instead.

    I also set other types of resource handles to the no-resource value when the resource is free'd (which is typically only in the destructor of an RAII wrapper written to encapsulate the resource).

    I worked on a large (9 million statements) commercial product (primarily in C). At one point, we used macro magic to null out the pointer when memory was freed. This immediately exposed lots of lurking bugs that were promptly fixed. As far as I can remember, we never had a double-free bug.

    Update: Microsoft believes that it's a good practice for security and recommends the practice in their SDL policies. Apparently MSVC++11 will stomp the deleted pointer automatically (in many circumstances) if you compile with the /SDL option.

    0 讨论(0)
  • 2020-11-22 11:53

    If you're going to reallocate the pointer before using it again (dereferencing it, passing it to a function, etc.), making the pointer NULL is just an extra operation. However, if you aren't sure whether it will be reallocated or not before it is used again, setting it to NULL is a good idea.

    As many have said, it is of course much easier to just use smart pointers.

    Edit: As Thomas Matthews said in this earlier answer, if a pointer is deleted in a destructor, there isn't any need to assign NULL to it since it won't be used again because the object is being destroyed already.

    0 讨论(0)
  • 2020-11-22 11:54

    "There are times when it is a good thing to do, and times when it is pointless and can hide errors"

    I can see two problems: That simple code:

    delete myObj;
    myobj = 0
    

    becomes to a for-liner in multithreaded environment:

    lock(myObjMutex); 
    delete myObj;
    myobj = 0
    unlock(myObjMutex);
    

    The "best practice" of Don Neufeld don't apply always. E.g. in one automotive project we had to set pointers to 0 even in destructors. I can imagine in safety-critical software such rules are not uncommon. It is easier (and wise) to follow them than trying to persuade the team/code-checker for each pointer use in code, that a line nulling this pointer is redundant.

    Another danger is relying on this technique in exceptions-using code:

    try{  
       delete myObj; //exception in destructor
       myObj=0
    }
    catch
    {
       //myObj=0; <- possibly resource-leak
    }
    
    if (myObj)
      // use myObj <--undefined behaviour
    

    In such code either you produce resource-leak and postpone the problem or the process crashes.

    So, this two problems going spontaneously through my head (Herb Sutter would for sure tell more) make for me all the questions of the kind "How to avoid using smart-pointers and do the job safely with normal pointers" as obsolete.

    0 讨论(0)
  • Setting pointers to NULL after you've deleted what it pointed to certainly can't hurt, but it's often a bit of a band-aid over a more fundamental problem: Why are you using a pointer in the first place? I can see two typical reasons:

    • You simply wanted something allocated on the heap. In which case wrapping it in a RAII object would have been much safer and cleaner. End the RAII object's scope when you no longer need the object. That's how std::vector works, and it solves the problem of accidentally leaving pointers to deallocated memory around. There are no pointers.
    • Or perhaps you wanted some complex shared ownership semantics. The pointer returned from new might not be the same as the one that delete is called on. Multiple objects may have used the object simultaneously in the meantime. In that case, a shared pointer or something similar would have been preferable.

    My rule of thumb is that if you leave pointers around in user code, you're Doing It Wrong. The pointer shouldn't be there to point to garbage in the first place. Why isn't there an object taking responsibility for ensuring its validity? Why doesn't its scope end when the pointed-to object does?

    0 讨论(0)
  • 2020-11-22 11:58

    If you have no other constraint that forces you to either set or not set the pointer to NULL after you delete it (one such constraint was mentioned by Neil Butterworth), then my personal preference is to leave it be.

    For me, the question isn't "is this a good idea?" but "what behavior would I prevent or allow to succeed by doing this?" For example, if this allows other code to see that the pointer is no longer available, why is other code even attempting to look at freed pointers after they are freed? Usually, it's a bug.

    It also does more work than necessary as well as hindering post-mortem debugging. The less you touch memory after you don't need it, the easier it is to figure out why something crashed. Many times I have relied on the fact that memory is in a similar state to when a particular bug occurred to diagnose and fix said bug.

    0 讨论(0)
  • 2020-11-22 11:59

    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.

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