As an aside, there’s something that I do personally that has now spread throughout my company, when doing in-band errors in C:
return perror("failed"), -1;
Basically, we use the semantics of the comma operator to avoid a new statement block. The expressions prior to the -1 (or whatever sentinel you choose) are just cleanup/reporting expressions. Another common example:
return free(foo), NULL;
It keeps the cleanup and the error return close together, and saves vertical space.
One of my personal favourites is libexpat. If XML parsing errors occur, it will bail; but if library errors occur in one’s callbacks, one must call XML_StopParser() prior to returning instead of having a return code indicate error.
Of course, in order to find this, is there apropos expat or anything? Hell no! Read expat.h and use your love of solving mysteries to guide you.
(In writing this, and in looking at expat.h to remember which function indicated error, I searched the web to find if there exists a manpage for libexpat. Turns out I was angry at this five years ago, too: expat.3 manpage. Meh.)
I personally dislike errno. It might have made sense in the time when all code was single-threaded, but these days, you have to know what kind of system you have to use it in a thread-safe way. On most modern systems, errno is actually a thread-local variable so you’re fine, but that’s not a guarantee for all systems that exist. So it can hurt portability if your application is multithreaded.
Posix requires that errno be thread local.
I still think it’s a cruddy interface, but it isn’t quite that broken.
What systems do not make errno thread-safe? I literally can’t think of one that doesn’t have thread-safe errno, as they all implement POSIX.1c for posix threads.
If they don’t implement posix threads, I probably don’t write any C for them.
What systems do not make errno thread-safe?
Old and buggy ones, and bad libcs on embedded systems and Esoteric-OS (though altogether this is getting rarer and rarer as time marches forward; like said, the advent of TLS has largely reduced the pain of errno across the POSIX land). errno is probably my least favorite C programming wart, and the easiest way to teach young programmers the dangers of global variables.
strtol has always amazed me. It’s almost easier to write your own conversion function than to get the check for the success of strtol right.
I believe usually the first check is ep == buf rather than buf == '\0', because that is what you need to check if you wish to continue scanning after the number as well. This just happens to work because in the case where buf is equal to ep, the first char will be either the zero terminator or not.
ep == buf
buf == '\0'