4 ms·
This is The Way To Do It. I take minor issue to calling free(NULL) abuse, though (I know you get it, but allow me to soapbox). I've known programmers who get
by mieko 11y ago
This is The Way To Do It. I take minor issue to calling free(NULL) abuse, though (I know you get it, but allow me to soapbox). I've known programmers who get squeamish relying on this, as if it's a hack, even though it's been mandated by the standard forever. It's like they believe someone would put together a fully-functional libc and miss that simple requirement somehow.
I think the C standard library would be easier to work with if they would've taken this further, and required, for example, fclose(NULL) to be a no-op.
- asveikau 11y agoIf you want to get nitpicky, you could also say there is performance cost to jumping into libc.so for free, then having it do a null check for you, then jump back to your code. Maybe that's worse than doing the null check more "locally". But I do make a point whenever I'm writing C, if I write a cleanup function for a new type of struct or whatever, cleaning up null is always a no-op. It just makes life slightly less tedious. Having to remember which functions do this and which don't, I'll admit, is annoying.
- caf 11y agoOn the other hand, replicating if (p != NULL) checks across your codebase will have a higher I$ footprint than sharing a single check inside free(), so the overall performance impact could easily be positive.
- lucozade 11y agoI would venture that, if a few (essentially no-op) .so function calls are likely to affect performance to a point that you care, allocating and de-allocating heap memory under those same conditions might be a bit more of an issue. Depends on the detail of the use case of course, but assuming that NULL cleanup is more the exception than the rule this is definitely a case of profile it first for me.
- nitrogen 11y agoI think the C standard library would be easier to work with if they would've taken this further, and required, for example, fclose(NULL) to be a no-op. There's always the counterargument that cleanup code that hides a missing allocation can mask bugs elsewhere, if for example a FILE * debug was never fopen()ed, only gets written to in exceptional cases, and fclose(NULL) ignores.
- mieko 11y agoI'd personally err on the side of clearer clean-up code, but this a good point (and a view shared with glibc and BSD-derived libcs that intentionally segfault in this case).
- userbinator 11y agoI wouldn't describe that as an "intentional" segfault, but rather a "natural" one, the default behaviour you get on a system with an MMU. The null case with free() is a special-case extra check explicitly inserted in the code.
- mieko 11y ago"Intentional" was perhaps the wrong word for glibc, but BSD libc (at least on FreeBSD and OS X) actually document it as intentional: NOTES The fclose() function does not handle NULL arguments; they will result in a segmentation violation. This is intentional - it makes it easier to make sure programs written under FreeBSD are bug free. This behaviour is an implementation detail, and programs should not rely upon it. I thought I remembered similar wording for glibc, but I appear to have been mistaken.
- simula67 11y agoWhy not put each allocated pointer to a linked list and on cleanup pick each element and call free() ? Same approach can be used for files also.
- hyc_symas 11y agoI think I just heard someone say "Mozilla". NSPR's free() wrapper crashes when given NULL. http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=commit;h=14868fcab658f32914a37a10ca1660d76c099811 http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=co... http://www.openldap.org/its/index.cgi/Software%20Bugs?id=7783 http://www.openldap.org/its/index.cgi/Software%20Bugs?id=778...