Sunday, November 19, 2006

C Follies:

So here I set the stage for what can only be called a "Geek Moment." I find myself sitting at work like a good student employee, but like every other Sys Tech on the planet with nothing to repair, I look to the Internet for entertainment and there I find the all mighty instant messenger. On this interesting communication tool, I converse with a very good friend of mine who will just be referred to as Derr in order to reserve some level of confidentiality. Derr and I, both computer science majors but at different Universities, often find ourselves talking about computer related topics and on this day we spoke about the C programming language and its follies. The main issue with C's follies is that they are not so much a problem with the programming language, its the fact that the average programmer lacks the understanding of what is actually happening behind the scenes and have been spoiled with languages like Java that will raise a compiler error when trying to do something that could later be viewed as "stupid" by the system.

Allow me to begin with a simple code segment:

#include

int main(int argc, char** argv){
printf("%d\n%d\n", 100==true, 1==true);
int x = 100;
if(x)
printf("true\n");
else
printf("false\n");
}

Here the standard bool type has been included and thus the macros for true and false are able to be used, as C defines it: false = 0 and true = anything not 0. And thus the statement "100==true" should evaluate to true (or as the system defaults, a 1) as well as the statement "1==true" then we go into the if statement where if(x) is translated "if x is true, then do ." Which should print out the string value "true" or so most would think from their first look at the code, but in fact that is not how C evaluates this expression.

So what happens when this code is compiled and ran? (compiled with "gcc testbool.c -o testbool")

max@iPseudogen:~/cTheory$ ./testbool
0
1
true

Why does this happen? I'm not entirely sure, but I assume its because the logical operator == does not logically compare in the same manor, or abide by the same rules, as an if statement comparison. I would also assume this could make for some interesting program run time characteristics if one was to use a bool returning function and expect C to follow its own rules about the bool type as stated above.

Next, something slightly more complicated and brings up the point of how a programmer who does not understand the inner workings of a system could fall into error by bad programming technique:

int *x;

void f(){
int y = 1;
x = &y;
}

void g(){
int y = 400;
}

void main(){
f();
printf("%d \n", *x);
g();
printf("%d \n", *x);
}

What happens when this is compiled and run? (" gcc stackframe.c -o stackframe.c")

max@iPseudogen:~/cTheory$ ./stackframe.c
1
400

Now, why would this give different output if the printf statements are verbatim?
When the function f() is called, the system puts its function call on the "call stack" and since the local int variable y is created within the function, its memory allocation is also performed in the stack space. Then x, an int pointer, is assigned the memory location of the local variable y the programmer has now saved the address to a position in the stack space. Why is this bad? Well, it is demonstrated in this example. When the next function call is made, the first function is now finished and popped off the stack, the memory space on the call stack is deallocated, in order to be used later by another function and the system does just that: it uses that space for the next function and (low and behold), it defines a local variable as well and places it in the memory location that the previous locally defined variable was held in. Thus, we have demonstrated the ability to alter a global variable by defining a local variable and assigning it a value. Why is this bad? Well, go write some large scale project and have this be one of the errors in it, debugging would be fun don't you think?

I must make a disclaimer that Derr was the one who came up with the code examples and all credit must be given to him, so uhmm... yeah, that was the disclaimer.

Are there more little interesting things like this? Of course, I'm sure there are C follies that Derr and I have never heard of, but these were the ones discussed on that day and found it interesting enough to blog about while I sit here on my couch with my Xubuntu powered iBookG4 bored out of my mind. Now are there tools out there to catch things like this in C code? Yeah, probably ... just thought this was good food for thought.

-Adam

No comments: