Monday, September 22, 2014

Undefined Behavior and Bad Code



I see a distressing number of people asking what the effect of really bad code should be. Code like this:
  printf(“%d %d %d”, ++i, i++, i);
or this:
  i = i++;

In C, both of these are intentionally undefined (the implementation can do with them as it pleases). You shouldn’t write this code in C. I think these are both defined in C# (replacing printf with Console.WriteLine), and I’m not willing to look it up for reasons I’ll get to in a second. For the purpose of this discussion, let’s say that these are defined in C#. If that’s true then you shouldn’t write this code in C# either.

But…but you just said it was defined!

Defined isn’t the same as “good.” Let’s write some code that checks someone in at a health club. First, we need to make sure the member is active, and throw an exception if they’re not. Then we need to update the last time they checked in to now. That would look something like this:

if (!member.IsActive)
{ throw new NotActiveException(member); }
member.LastCheckinTime = DateTime.Now;

Now let’s go back to one of our offending lines.
  i = i++;

Amateurs write code for the computer. Professionals write code for other people who are reading the code (although it’s important that the computer understand it also). So what is this code trying to do? I mean, I can read the code. It’s adding 1 to i  and also setting i to the value it gets as the result of…ugh. What is the goal here?

If the goal is “add 1 to i,” then clearly you’re doing it wrong.
  i++;
Done. And this line, what is its goal?
  printf(“%d %d %d”, ++i, i++, i);

If the goal is “try this and see what happens,” then I’m not sure you care whether it’s undefined or not. But let’s say you actually want to do something useful. The variable i is used as a loop variable enough to make it understandable, as long as it doesn’t mean anything else. If it means “days after the base date,” maybe we could call it, I don’t know, daysAfterBaseDate? So would anyone want to try to take a stab at code where it makes sense to print variants of a value this way three times, and happen to add two to it in the process? That is, what meaningful variable name could you put there in place of “i" that makes this statement make a lick of sense?

I can’t think of one either.

No comments:

Post a Comment