This was written in January of 1990, but is still meaningful
today, though we do have better debugging tools now. This
was originally published in the Boston Computer Society's PC Report.
I admit it: I'm sometimes just not careful where I'm pointing. In
ordinary life, careless pointing might be rude, but in C programming, it
tends to be unforgivable.
Right now, for example, I'm chasing an errant pointer that cannot be
found using Codeview (Microsoft's debugger). That is, if run under
Codeview, the program works correctly, but crashes when run without it.
This might sound like a real hair-tearer, but usually this kind of
problem isn't too hard to find. Usually, that is.
If a program works under a debugger but crashes otherwise, the
problem is almost always an uninitialized pointer. The reason it
works during debugging is because the debugger either provides
initialization or happens to arrange memory so that your error doesn't
hurt anything important. Every time this happens, it turns out that
I've screwed up. Every time. All I have to do is find where I
made the mistake.
This particular pointer is hiding very well. So well that it actually
is hard to crash it on my machine: I have to feed it garbage data to
see the problem. On my client's hardware, it pops up without provocation,
and destroys screens, rampaging through data in memory, changing this and
discarding that, and ultimately exits with the dreaded "Null Pointer
Assignment" message. Sometimes. Other times, the program just clicks
along, doing its thing. Frustratingly random, so very hard to find.
It is tempting (so very tempting) to blame this on hardware. We are
talking about an off-brand machine, and a 386SX at that. "Works OK here",
wash my hands and walk away. Trouble is, everything else in the world
works fine on that box. Every diagnostic gives this machine a totally
clean bill of health. And there is that nagging reality that, albeit with
difficulty, I can cause the problem on my own machine. The error may be
esoteric, but it is real.
My first approach is calm and logical. I wrote the code, I understand
its intent, I am a supposedly intelligent person - I can find this by carefully
reading the source.
That lunacy lasts about ten minutes. There is no way I'm going to read 107K
of source code. In fact, I'm banging away at the keyboard before I'm
two screens into the first source file. Banging what? Why "printf"'s, of
course. Dozens of "The address of Dir_now is %p and the contents are %s\n"
thing-a-mungies are now cluttering the code. Remember Codeview is no help
because it works under Codeview. And DEBUG is no help because DEBUG is no help.
Days later I was back to the scientific approach. The printf's hadn't helped, and I was getting slap happy. I had visions of Kernighan and Ritchie
using excerpts of my code for a new book: "Making an unbelievable mess with C, a Case Study". I started adding sarcastic comments to my code:
/* Real smart using floats for "for next loops" */
/* Gee, do any of these variable names MEAN anything? */
I also started adding apologies:
/* Added this at 2:00 AM - need to fix */
/* Really rushed here - I can fix this later */
/* There's a reason for this mess here - honest */
Bald faced lies, of course, added only in case I had to enlist someone
else to help me find this thing.
The Zen approach seemed worth a try. You know, you just inform your
subconscious that this problem is serious, and then you go off
and do something else. Within a few days, the solution will magically
appear, perhaps in a dream. My subconcious had to be aware of how distressed
I was - would I absent mindedly pop a handful of our pet gerbil's food
pellets in my mouth were I not stressed? So I decided to do something
else for a day or two. No luck: my subconscious has apparently moved to
Cincinatti; I haven't heard anything from it in weeks.
Yesterday I gave a copy of my code to a friend in hopes he can spot
the problem. I'm getting desperate here..
My friend called, opening with caustic comments about aesthetics and user
friendliness, peppered with snide observations on sloppy coding. "But
does it crash on your box?", I asked. "No, it doesn't, unless I feed it
your 'bad' data. You have an uninitialized pointer." Hopefully I asked,
"Do you know where?". He laughed. "You know what you have to do, right?"