There seem to be two arguments why one should set a pointer to NULL
after freeing them.
Short
The answer depends on (1) project size, (2) expected lifetime of your code, (3) team size. On a small project with a short lifetime, you can skip setting pointers to NULL, and just debug along.
On a big, long-lived project, there are good reasons to set pointers to NULL: (1) Defensive programming is always good. Your code might be ok, but the beginner next door might still struggle with pointers (2) My personal belief is, that all variable should contain only valid values at all times. After a delete / free, the pointer is not a valid value anymore, so it needs to be removed from that variable. Replacing it by NULL (the only pointer value that's always valid) is a good step. (3) Code never dies. It always gets reused, and often in ways that you haven't imagined at the time you wrote it. Your code segment might end up being compiled in a C++ context, and probably get moved to a destructor or a method that gets called by a destructor. The interactions of virtual methods and objects that are in the process of being destructed are subtle traps even for very experienced programmers. (4) If your code ends up being used in a multi-threaded context, some other thread might read that variable and try to access it. Such contexts often arise when legacy code is wrapped and reused in a web server. So an even better way of freeing memory (from a paranoid standpoint) is to (1) copy the pointer to a local variable, (2) set the original variable to NULL, (3) delete/free the local variable.
If the pointer is going to be reused then is should be set back to 0(NULL) after use even if the object it was pointing is not freed from the heap. This allows for valid checking against NULL like if (p){ //do something}. Also just because you free an object whose address the pointer is pointing to doesn't mean the pointer is set 0 after calling on delete keyword or free function at all.
If the pointer is used once and it is part of a scope which makes it local, then there is not need to set it to NULL being that it will be disposed of from the stack after the function returns.
If the pointer is a member (struct or class), you should set it to NULL after freeing the object or objects on a double pointer again for valid checking against NULL.
Doing this will help you alleviate the headaches from invalid pointers like '0xcdcd...' and so on. So if the pointer is 0 then you know it is not pointing to an address and can make sure that the object is released from the heap.
Both are very important since they deal with undefined behaviour. You should not leave any ways to undefined behaviour in your program. Both can lead to crashes, corrupting data, subtle bugs, any other bad consequences.
Both are quite difficult to debug. Both can't be avoided for sure, especially in case of complex data structures. Anyway you're much better off if you follow the following rules:
If you don't set the pointer to NULL there is a not-so-small chance, that your application continues to run in an undefined state and crashes later on at a completely unrelated point. Then you will spend a lot of time with debugging a nonexistent error before you find out, that it's a memory-corruption from earlier.
I'd set the pointer to NULL because the chances are higher that you'll hit the correct spot of the error earlier than if you didn't set it to NULL. The logical error of freeing memory a second time is still to be thought of and the error that your application does NOT crash on null-pointer access with a large enough offset is in my opinion completely academic although not impossible.
Conclusion: I'd go for setting the pointer to NULL.