Archive for the 'Watch For' Category

When You Miss The Case

Wednesday, January 31st, 2007

One rainy day you write some code in C++, and compile it with no errors. It might just work, you hope. You run it and it just doesn’t do what it should be doing. You debug it, look at it, think about it, tweak it… but… nothing! You try to understand. The code is there. Only a few lines, doing something that doesn’t seem right.

[Am I going mad?]

typedef enum
{
	FIRST_ONE,
	SECOND_ONE,
	THIRD_ONE
} T_states;

int main()
{
	T_states x=FIRST_ONE;

	switch(x)
	{
		FIRST_ONE:
			printf("First one! Yeah.n");
			break;
		SECOND_ONE:
		THIRD_ONE:
			printf("Second or third one?n");
                        break;
		default:
			printf("None of them!n");
                        break;
	}
	return 0;
}

…you find yourself kneeling down in front of your desk with your fists ready to smash the screen… then… with your amazement… you figure it out… you completely missed the case… Bad words associated with the compiler pop to mind.

There are mistakes that you never made, and that you’d never think you would make. When you do make them, you just don’t see them, because everything looks so innocent and normal… except… that you missed the darn case…

Yep, the code above compiles just fine. No errors, at least not with VS and with another embedded compiler I’ve compiled it with. In fact, it is perfectly syntactically valid code. Evil, but valid.

When you run this code it prints “None of them!”. Yep. You missed the case!!!! (the “case” keywords before the constants inside the switch).

The compiler takes “FIRST_ONE”, “SECOND_ONE” and “THIRD_ONE” as goto labels, and doesn’t complain. Everything compiles. Obviously when you run it, the execution runs straight to the default case.

Never miss a case, especially when you are tired!! :)

Nulling Pointers With memset

Wednesday, January 24th, 2007

Let’s say that you have the following structure:

struct
{
     char *sPtr1;
     char *sPtr2;
} S_something;

In C it is very tempting to initialize such a structure with something like:

   S_something s;
   memset(&s,0,sizeof(S_something));

That code seems OK at first, but there is a subtle issue. Can you spot it?

The problem is that this code is not always portable!! Most of the time you’ll be fine, however depending on the system (in rare cases, I admit) a null pointer might not be represented by a bitwise zero, but something else. In fact in some architectures 0 is a valid address (Example: IBM z/Architecture)

When you use memset to initialize the structure above, you are forcing the pointers in the structure to be set to bitwise zero. As noted that might not be equivalent to null, creating all sort of issues.

Conversely, when you assign a pointer to “0″ or to “null” on one of these systems, the compiler does the conversion automatically. memset doesn’t.

I’ll give you an example. The following code:

   S_something s;
   memset(&s,0,sizeof(S_something));
   if (s.sPtr1==0) printf("Good");
       else printf("Bad!");

Could potentially print “Bad!”.

Solution: simply initialize the structure by hand:

   S_something s;
   s.sPtr1 = 0;
   s.sPtr2 = 0;

This is guaranteed to work on all ANSI C compliant compilers.