4 ms·
A simple way to approach this problem in C, that will work in most cases, is something like this: void safer_free(void **x) { if(x!=NULL && *x!=NULL)
by ktRolster 9y ago
A simple way to approach this problem in C, that will work in most cases, is something like this:
void safer_free(void **x) {
if(x!=NULL && *x!=NULL) {
free(*x);
}
*x = NULL;
}
the key part being to set the original pointer to NULL so a future use will cause an exception, not a vulnerability.
- TheSoftwareGuy 9y agoExcept this won't work when multiple pointers exist to the same data.. which is arguably when this kind of stuff is most difficult
- lossolo 9y agoIf you have multiple pointers to the same data with different lifetimes you already need some kind of reference counting or garbage collection.
- ktRolster 9y agoThat's why "safer" :) It works in the vast majority of cases. In the rare other cases, you should spend some extra thought on your pointer usage to make sure you have a set of abstractions that let a human reason about the memory sensibly (either that or an insane number of test cases to catch any problem). Someone else mentioned reference counting, and that can be a good idea. The bottom line is you need to do something to make sure you're not doing use-after-free, and it's mostly not difficult.
- marcosdumay 9y agoIt works on most cases that people normally get right, and is useless on most cases that people normally get wrong. Overall, it's not useless, but it's really not worth modifying the language for it.
- panic 9y agoMinor pedantic note: the *x!=NULL check is unnecessary. Calling free(NULL) is specified to do nothing.
- shandor 9y agoI was just going to post a comment asking why your proposed way is not the standard way. Surely free is (usually) not called that often that the overhead would be anything close to unbearable? This seems like a so simple method of handling most of the cases, as you point out, that I feel I'm missing some obvious downside.
- to3m 9y agoThere is no generic pointer-to-pointer in C. You get an incompatible-pointer-types warning in gcc when trying to use void * * : https://godbolt.org/g/vxWFvl https://godbolt.org/g/vxWFvl There is probably scope for use of C11 _Generic, but I don't think you could support user-defined types in that way. The usual macro problems apply when trying to do it as a macro: #define FREE(X) (free(X),(X)=NULL,(void)0) In C++ you can do something like this, which works well enough: (I don't use this specifically myself, but I have something similar for COM objects) template<class T> static void Free(T *&p) { free(p); p=nullptr; } This isn't completely useless, but it's not worth sweating blood over. Personally I think I've had more mileage from good-quality debug functionality in the memory allocator: fill newly-allocated and newly-freed regions with junk; check junk and metadata periodically; unmap regions promptly; and so on.
- ktRolster 9y agoWhen the language was made 40 years ago, the extra overhead was unbearable. Or rather, more likely, they were so focused on efficiency (because that's what you do when you have a 1Mhz computer), that the idea of making things easier for people in this way didn't cross their mind.