SAFE_DELETE and SAFE_FREE. What do those functions (macros?) say to you? What if you also have over-ridden calls to DELETE and FREE too?
I think most people see a safe delete function as one that handles a null pointer safely – only calling delete or free when the ptr isn’t null. Since this is totally irrelevant (‘delete null’ is a no-op as defined by the standard and free(null) seems to be just as safe) there’s nothing special or even needed here.
So the ‘safe’ part must be something else?
What about the usual delete/free over-ride behaviour of setting the pointer to the free’d memory to null itself. Well, that’s just common sense. No-one wants dangling pointers left lying around as that way only leads to memory over-rides and random crashes (usually in the submission candidate build 10 minutes before it needs to be uploaded). So if that’s the reason, then to be honest the macros should be called SENSIBLE_FREE or REASONABLE_DELETE. But then that’s just daft.
I suppose you might have a situation where setting it to NULL isn’t really necessary.
delete myPointer; /* myPointer = NULL */ // Don't need this now myPointer = new SomeClass;
But seriously, is having an extra line setting ‘myPointer’ to NULL a problem in the grand scheme of things? Any half decent compiler would probably strip it out anyway, and besides you’re freeing and allocating memory – an assignment isn’t going to mean squat in the middle of that.
Thinking some more, you might also have a const pointer, that cannot be set to null. This, I suppose, is an issue, but it’s an interesting one, that gets into the realms of what’s a const pointer (or a pointer to const data) represents to the user? I don’t want to cover that here, as it could take pages and pages (and generate lots and lots of comment), but it’s a case that is rare and isn’t something that should be seen as ‘the norm’.
Another possibility is that these ‘safe’ functions are doing a little extra. Maybe in debug, the heap code is checking that this pointer was actually allocated in the same heap you are trying to free it from, or if indeed it was allocated at all. Safe in this context seems to be more like ‘close your eyes and hope for the best’ kind of safe. It’s all good and well being safe in debug, but I’m guessing code like this isn’t run in master builds, so you’re left with finding problems in master, when it becomes so much harder to track down issues of any kind. It’s much better to have these problems flagged at the earliest opportunity, so doing these kinds of checks in a vanilla over-ride makes more sense than doing it in a ‘safe’ version.
So really, there is nothing ‘safe’ about functions like these, nothing they do that wouldn’t be carried out by a programmer in their day to day work. So why do so many libraries have different versions of an over-ridden function, ones which are ‘safe’ and one’s which, apparently, are not.
So just bite the bullet and reduce the number of functions that a programmer can call to delete some memory. Have one version of FREE and one version of DELETE (or SDK_FREE and SDK_DELETE to make the distinction obvious) that hooks into your memory manager, making NULL a no-op and making the pointer in question a NULL pointer when it’s done. Reducing the number of available functions makes even more sense if the function is actually a macro, as with no scoping available, polluting the namespace is something you really want to avoid.
And this isn’t just about FREE or DELETE. Reduce your macros, reduce your function calls and make your code easier to use, easier to understand and easier to test as a result.