OdeToCode IC Logo

Language Lawyers (and Nasal Demons)

Friday, July 30, 2004
As soon as a development language has an official specification behind it, the first language lawyer appears. If you’ve never seen one in action, they are the type who can rattle off section and paragraph numbers from a specification while explaining the bizarre behavior of some code snippet. You might see them write something along the lines of:

The values of a and b are automatically promoted back to int [], which is then the type of the result of the / operator []. Since -32768 is exactly divisible by -1, and the result of 32768 is representable in the type int, the division must yield this value.

Nearly every language with a specification will describe situations with “undefined behavior”. Undefined behavior means there is something so horribly screwed up in the code, or in the data, that the program is probably going to crash spectacularly. Except specifications never use the word ‘crash’. Many of them, including the C# spec, will use the more dignified phrase: “unpredictable results”.

Now language lawyers, not really being lawyers, have a sense of humor. Since the phrase “unpredictable results” leaves the outcome so open-ended, they will say undefined behavior could, in fact, lead to demons flying out of your nostrils.

The first apparent reference to demons and noses came in a 1992 post to the comp.std.c newsgroup. The post contains many paragraph and section number references to the C language specification, but ends with this little gem:

In short, you can't use sizeof() on a structure whose elements haven't been defined, and if you do, demons may fly out of your nose.

The phrase caught on.

In the mid 90’s I was maintaining a C code base intended for both an 8 bit Hitachi chip and the PC, so I was interested in writing portable ANSI C programs and followed the comp.std.c and comp.lang.c newsgroups. I don’t know how many times someone would come along and post code which started like this:

void main (void)

As soon as the above line appeared the language lawyers appeared in force. You could look at the code, and see it was only one semi-colon away from curing world hunger, but it didn’t matter, because the response was invariably something like:

The Standard says that declaring main as returning void invokes undefined behavior. Beware the nasal demons.

Although sometimes the lawyers would make other amusing comments:

if you write:

void main (void) 

it's *possible* (under the rules of C) that your computer will pogo round the room whistling the star spangled banner. It's very unlikely, but C isn't interested in "likely".

Whenever I was having a really bad day, I’d write a program with main returning void just to see what would happen. I tried it with the Microsoft C compiler, the Borland C compiler, the Intel C compiler, and the now defunct Boston Systems Office C compiler. I was hoping to create a horrible, slimy demon who I could train to stand at my office door and terrify people trying to enter with requirements documentation in hand. Not only did I never get a demon, the programs always worked without any errors. Shows you what the language lawyers know.

In any case, I’m hoping to find some good examples of undefined behavior in C# or VB so I can try to invoke nasal demons from .NET. I imagine it will be much harder to do with a managed runtime in place, but if you know of any opportunities, please let me know.

Andy Friday, July 30, 2004
Undefined behavior never ends up being as exciting as it sounds. Usually it's something very tame that when printed looks like:
<br>The really exciting stuff happens farther down if you forgot to trap for it and assign a pointer of type Foo to that result and then try and access some member of type Foo. Then the really cool sh!t happens!
Andy Friday, July 30, 2004
*cough ehem cough*
<br>Also the following stories are still be waited upon:
<br>The intern who wore pink teddy bear clips in his beard.
<br>The CEO who painted his toenails the company colors.
<br>The CFO who was amazed to see how Excel could recalculate cell C3 based on the contents of cell C1.
<br>The CTO who enlisted the aid of a software developer in chasing down escaped chickens back at the farm.
<br>What it is like to show up for work at a new company and see the office furniture from my last company being delivered by tractor trailer.
<br>Why I should not be given the opportunity to take the helm of a yacht for any length of time.
<br>What it is like to have a practicing gastroenterologist at the office part time and how this leads to errant phone calls from people describing the odd color of their stool and demanding advice on what to do about it.
<br>The vice president of global sales who drove a different vehicle to work each day yet never made a sale, and why I think this is because he wore Hawaiian shirts and Nikes during appointments at Fortune 50 companies.
<br>Last but not least: Why engineers should not be required to move office furniture when moving to a new building.
Michael Giagnocavo Sunday, August 8, 2004
Well, um, the IL opcode cpblk requires that the source and destination don't overlap. So you could write a program that does overlap the src and dst and see what happens. (I found this out while writing my encrypted loader for InvisiSource.)
<br>Of course, you'd have to be an uber-geek to want to do this, and bored out of your skull (or high) to actually do it: &quot;Oh look! a few bytes in memory are different values. cool.&quot;
Scott Allen Tuesday, August 10, 2004
I'm am in dire need of some demons at work this week. Big nasty demons with large teeth and foul breath.
John F. Woods Monday, September 20, 2004
As the author of the original &quot;demons may fly out of your nose&quot;, I'd like to point out that the real point of the &quot;undefined behavior&quot; discussions was not to assert that bizarre behavior must necessarily result from incorrect or undefined code; it was to defeat the frequently seen argument that &quot;compiler X is junk because it doesn't generate correct code for my program&quot;, where &quot;my program&quot; inevitably included an instance of undefined behavior (dereferencing NULL, sizeof(struct undefined), or whatever). Merely replying &quot;the standard says you shouldn't&quot; never convinces these people; they always come back with &quot;well, compilers Y and Z do what I expect, so obviously I'm right&quot;, followed closely by &quot;how can the standard possibly permit a compiler to output broken code even if a construct isn't officially defined?&quot; Thus there was an ever escalating insistence that &quot;undefined&quot; does not mean &quot;whatever the user thinks would make his broken program work&quot;, it means &quot;undefined by the standard and beyond the pale of the language&quot;.
<br>Compilers aren't obligated to mistreat programmers who step outside the language definition, but they certainly aren't obligated to treat them kindly, and a compiler which &quot;works&quot; one release with an incorrect construct may not &quot;work&quot; the next release -- even though the compiler is, in fact, perfectly conforming in both cases. (Although there have been some programmers who I *wished* had compilers which formatted their hard drives when undefined language constructs were used...)
<br>(I just idly decided to go googling for &quot;nose demons compiler&quot; to see how many references to the idea were still floating around.)
Comments are closed.