In 1983 my math teacher wrote on the blackboard: P{Q}R
. Ever since, my code is loaded with assertions. “Assertions should be used to document logically impossible situations and discover programming errors […] This is distinct from error handling: most error conditions are possible, although some may be extremely unlikely“. (Wikipedia) [Assertion] We all have seen, but never produced, anti-code like:
assert(buf = malloc(128));
However, I have produced code like:
assert(!"Sorry, PNG routines not implemented yet.");
Fix-me-later-code like this might get shipped (with or without NDEBUG
)… and some user might try a PNG file… after six hours of typing… without saving… We have all been there. You balance a todo-list of 20 items in your head, and it won’t survive deep thought on some unlikely potential problem. Put in an quick assert()
and you can continue to work on your todo-list of, now, 19. The problem is not in using the assert()
, but in forgetting to replace it with real code, eventually. So here is how I make them stick out:
#define NOT_HANDLED_YET(b)
(void)(!(b) || exit_error("Error '"#b"' not handled yet!"))
#define NOT_IMPLEMENTED_YET(s)
(void)exit_error("Sorry, "s" not implemented yet!")
The examples above would read:
buf = malloc(128);
NOT_HANDLED_YET(NULL == buf);
NOT_IMPLEMENTED_YET("PNG routines");
And remember, no commits on trunk unless grep -c NOT_ *.[ch]
returns 2
.
And perhaps to help you remember, make it stop compiling the moment you turn off debugging as well:
#ifdef DEBUG
#define NOT_HANDLED_YET(b)
(void)(!(b) || exit_error(“Error ‘”#b”‘ not handled yet!”))
#define NOT_IMPLEMENTED_YET(s)
(void)exit_error(“Sorry, “s” not implemented yet!”)
#else
#define NOT_HANDLED_YET(b) THROW A BIG COMPILER ERROR HERE
#define NOT_IMPLEMENTED_YET(b) THROW A BIG COMPILER ERROR HERE
#endif
Funny you should say that. (Small minds think alike?) But I had several versions like that with #error (ANSI), #warning (GCC) and even (_i/(_i-_i)) to force a core dump. On a related note, I once lost hours on #pragma being ignored by the compiler. And btw, I would use #ifndef NDEBUG, to make it compatible with the way assert works. But that is just personal taste.