C Pointer Problems
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 excepts 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?”
Yes, unfortunately I do. Back to the “printf”‘s.
*Previously published at APLawrence.com
A.P. Lawrence provides SCO Unix and Linux consulting services http://www.pcunix.com