Thursday, September 16, 2010

Nasty C Behavior

This will probably be part of a continuing series of rants about how the C language has nipped me. This time it is due to not properly prototyping functions. If you want to play it safe with C, it is a bare minimum that all functions have proper prototypes before their first usage.

I have been moving some C code from my 32 bit development computer to our 64 bit cluster. The way C (or maybe just gcc) deals with functions that don't have prototypes is to assume that the return value is an int. The tricky part is that on some systems an int and a pointer are very likely the same size. If this is the case, the C picture of data is just bits, interpret them however you like, means you will probably get a warning but the program will run fine.

But the relationship between the width of a pointer and an int is in no way guaranteed. When I moved the code to the 64 bit cluster, the implicit prototype meant the compiler expected the function to return an int, but it instead returned a pointer, and on the cluster a pointer is 8 bytes wide while an integer is 4 bytes wide. This led to a problem where the code worked fine in development, but when moved to production it failed mysteriously.

All of this is further aggravated by the fact that I didn't write the buggy code. My boss wrapped some code from Numerical Recipes and neglected to include the header files. And it would have been caught years ago, but gcc is smart enough to fix this bug sometimes. It is not entirely clear when this will bite you and when it won't, so my new plan is to prototype everything I use and if something fails mysteriously, check the prototypes first.