Four C Programming Anti-Idioms
Thomas Ptacek | January 29th, 2006 | Filed Under: Development
Excuse me, because this is off-topic to most of our readers, but very on-topic to me. The following are Four C Programming Anti-Idioms. Each one makes you go through extra effort to get worse code. Stop perpetuating them.
- Checking the return value of malloc()
Heresy! Blasphemy! Shoddy engineering!
Fuck you. So malloc() failed. What are you going to do about it?
If you’re 99% of the malloc-checking C programmers in the world,
when malloc fails inside a subroutine f(), you’ll do one of three things:
- You’re going to return -1 from f(). Then, to be safe, in each of f()’s callers, you’ll check f()’s return value, returning -1 on failure. This recurs all the way back to main(), where you will detect -1 and exit.
- You’ll return from f() without an abnormal error. f()’s callers won’t have an abnormal return value to check for, but that won’t matter, because by aborting f() you left the program in an unknown state and it’s going to segfault no matter what you do.
- You’ll immediately abort the program.
- You want the failed alloc to cause a segfault that you can catch and debug.
- You want the failed alloc to gracefully abort the program.
(1) is accomplished by doing nothing. (2) is accomplished by preloading a version of malloc() that checks its return value and gracefully aborts on failure (it’s 2006. Why are you wasting time with “xmalloc”? Did you remember “xstrdup” too? Didn’t think so.)
If you’re one of those clever people that wants to keep an “emergency reserve” of memory to gracefully close the whole program (instead of aborting), it’s still better to preload a new malloc than to explicitly check malloc’s return value.
Less typing, safer code.
- Casting void-star
It’s the void pointer’s job to stand in for other pointer types. In ANSI C99, the “cast” is implied when you pointers to or from void-star, and redundant when supplied explicitly.
So this:
int *i = malloc(sizeof(*i));is equivalent to this:
int *i = (int*) malloc(sizeof(*i));But the redundant int-star cast isn’t just extra noise. Because the “implicit cast” behavior is unique to void-star, casting explicitly hides an error: if variable types change (say, you add an argument to a function), and what you thought was a void-star ceases to be a void-star, a casted assignment will suppress a
valuable warning. For instance:
void *v = NULL; int *i = v; // just peachy long long *ll = NULL; i = ll; // warning: assignment from incompatible type i = (int*) ll; // no warning, broken assignmentYes, yes, I know, you can’t assign FROM void-star without a cast in C++. Stop using C++. And look askance at ANY pointer cast in straight C code.
Less typing, safer code.
- Passing pointers to tiny structures
You want to return a pointer to a buffer and its length. You use the equivalent of:
struct iov { u_char *base; size_t len; };On LP32, struct iov is as hard to pass in and out of a function as long long. Put differently, unless you go out of your way to individually allocate and pass pointers to long long to avoid the “overhead” (use of successive registers) of copying, you don’t get to pass pointers to struct iov.
Dragging the point out further, I could say that if you use long long in your code, you should be passing “pair” structs instead of using out-args to store lengths. But I’m not going to go there, because that’d be hypocritical even if it was correct.
Less typing, safer code.
- Wiring down pointer sizes in malloc()
Moral cousin to gripe (2). You can “dereference” an undefined pointer in a “sizeof” expression. So this:
v = malloc(sizeof(*v));equivalent to this:
v = malloc(sizeof(struct V));except that in the latter example, if the type of “v” changes, you have two places your code needs to change, and god help you if you forget and the resulting code compiles anyways.
Less typing, safer code.


Add New Comment
Viewing 16 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment
Trackbacks