Sunday, October 25, 2009

Insidious C bugs

Here's a couple novel C bugs that I've encountered recently (using gcc). Man, it sucks when these happen.

1) No compiler warnings when not instantiating structs correctly

The following code will give no warning indicating that you have not, when declaring an array of structs using the curly bracket notation, instantiated all members of the struct:
#include <stdio.h>

int main()
{
struct a_struct {
int a;
int b;
} buggy[] = {
{ 1, 2, },
{ 3, /* oops! */ },
{ 5, 6, },
};

int i;
for(i = 0; i < sizeof(buggy) / sizeof(*buggy); i++)
{
printf("%i: %i %i\n", i, buggy[i].a, buggy[i].b);
}

return 0;
}
Here's the ouptut:
0: 1 2
1: 3 0
2: 5 6
Oops! It would have been nice for the compiler to tell us about this...

2) Forgetting to delete the semicolon when turning an assert into an if statement

Say you have
assert(cond);
But you want to make it an if statement to have a little more debugging output when it triggers. So you change it to:
if(!cond);  /* oops! */
{
dump_stats();
assert(0);
}
Whoops! Now the if statement has an empty body and the block between the curly braces will always execute!

3) Strange things you can't do within case statements

This isn't really insidious so much as annoying -- why are you allowed to do some things inside a case statement (that don't seem to make sense) but aren't allowed to do others (that seem to make much more sense)? For instance:

int main() {
int i = 0;

switch(i)
{
int j = 5; /* fine */
case 0:
char ch; /* error */
break;
case 1:
i = 1;
char ch2; /* fine */
break;
default:;
char ch3; /* fine */
break;
}

return i;
}
Note the semicolon following the 'default:' There's a good discussion of this problem here. Essentially, the first thing after a label cannot be a declaration. The error that the compiler gives here is usually pretty cryptic, too.

Similar links

No comments: