I’ve recently spent quite some time integrating a lot of C code to turn it into production-ready software. It is surprisingly interesting, but the first few days are usually quite painful for these reasons:
Many C developers have done hundreds of projects, they always need logging but when an error occurred they still like to do some standard
fprintf(stderr, ... );. I use something similar to this. But you should at least insert the __FILE__ and __LINE__ macros. It will save lots of people hours of debugging.
Use the warnings
On gcc, you should always have
-Wall -Werror enabled. This will avoid a lot of stupid and horrible things.
Check the return codes, log the abnormal ones.
Sample code that can make you lose quite some time:
FILE * f = fopen("logs.txt","w");
if ( ! f )
THIS IS WRONG, we should have something like this:
LL_WARNING("Could not open log file !");
using this kind of macro.
You know how to count in bytes, how pointer and offsets work, that’s great. But you should also know that you can always replace this by a sizeof(). That way, we won’t have to be as smart as you to read your code (and fix it).
Great POSIX standard headers and libraries
The standard errors code already cover a lot of cases you could encounter.
You can use booleans including stdbool.h, it’s even standard.
Argument parsing is standard, don’t make your own strange argument parsing code that won’t even (fully) document.
Great non standard libraries
Like json-c to serialize your data, or zeromq to handle network communication.
Use a debugger
You might have forgotten it. But debugger will make you save a lot of time especially when they are well integrated in IDEs like netbeans. You can just immediately know why something crashed or why the programmed stalled for no apparent reasons.
In most of the cases, your compiler will do a great job. Don’t use inline, prefetching or any other crazy optimization unless you really know what you do.
Don’t re-create unreadable network protocols
Use something simple readable like JSON over zeromq. It’s easier to create, debug, monitor. Please don’t create a new binary protocol.
Learn other languages
Oops ? Did I just say that. YEAH I DID. C is fine but in many cases you can use something else that would give you a huge productivity boost, it will probably run slower and produce bigger binaries but in most of the cases it really doesn’t matter. When making network servers, python, go, node.js (java in some ways) make the job a lot easier.
Bad memory management
Leaks and buffer overflow can happen. And so as many other issues out there. This is why you should use valgrind quite frequently.
In C, “it worked fine on my computer” is not a good enough excuse. There are many memory mistakes that you will miss on a 64bits Linux with 8GB of RAM and that you will definitely see on a 32bits Linux with 128MB of RAM.
Use standard tools like
automake or create a simple and easy to maintain Makefile like this one.
Malloc is not your (only) friend
In most cases, allocating things on the stack is enough. A lot of developers seem to forget it. And it’s usually the same who forget to free their mallocated pointers.
It’s outside the scope of this rant but still:
It often feels like a big waste. Most Linux developers I know are pretty fast at doing C programs and yet they can’t seem to appreciate the use of a good IDE like netbeans. At least you should use something like sublime which is not an IDE but still gives a productivity boost.