Subtitle:
Microsoft's Techniques for Developing Bug-Free C Programs”
Author:
Steve Maguire
Publisher:
Microsoft Press
First published:
1993
ISBN:
1-55615-551-4

I don't normally buy books like this. In fact, I didn't buy this one either: I was given it by a neighbour (whom I don't think has read any of my code...) and thought it might be worth a skim. The writing is relatively conversational; chunks of it wouldn't feel out of place as posts to a technical blog. The book is a series of tips, presented with supposedly catchy titles such as “Inconsistency, the Gremlin of Code” (which I liked) and “Watch your Language” (which seems like a poor effort to me) and a couple of pages of plausible, but invented, motivating examples of ways in which trouble can strike, and the solution. These tips are grouped into eight categories: A Hypothetical Compiler discusses using warnings from the compiler, lint and similar tools to find potential bugs mechanically; Risky Business is about surprising aspects of the C language and differences between CPU architectures; and so on.

Scattered through the book are anecdotes about Steve Maguire's time working on early products (mainly Excel) for the Apple Macintosh at Microsoft, which provide insight into the company's development practices, and (more interestingly) how startlingly unwise they used to be. (Apparently, at one point standard practice was to leave fixing any and all bugs until the product was feature-complete. Uhm...)

Many of the suggestions made are fairly C-specific, as the subtitle suggests. Aside from advice directly relating to syntactic issues, many of the memory corruption-related bugs discussed cannot occur in safer languages, and higher-level tongues solve a number of portability issues for you. But other tips are more general: for instance, making functions do one well-documented job well rather than turning them into Swiss Army chainsaws is good practice in any language (and is one of the key tenets of UNIX-like systems). The advice given is sound, although sometimes seems hardly worth stating. Sure, code like

(x ? (y ? bacon : ham) : salami)("let's talk about pork")

is unreadable and unidiomatic, and would be better written as

if (x) {
    if (y) {
        bacon(message);
    } // etc.

...but no-one would actually write the former in C, would they? (Of course, functional languages are another matter!) There are also some omissions, one of which is Maguire's apparent failure to mention mandatory code review. I first encountered this practice when working on Telepathy-related projects, where all patches are reviewed by at least one other developer before being merged, and it seems to help avoid even relatively subtle bugs creeping in — more so, I claim, than would stepping through every branch of every function you write in a debugger, which is the subject of an entire chapter of Writing Solid Code.

It's a pretty solid book, but I wouldn't buy it. Too much of the advice is either obvious or irrelevant: I'm never going to write my own replacement malloc library, nor my own assert() macro. The space wasted in binaries by debug strings may have mattered in 1993, but it's negligible even on mobile devices fourteen years later. (Oh, and no-one's ever going to convince me that encoding type information in variable names is anything but redundant.1) But if you write C, and find yourself with a spare half hour and a copy from someone else's bookshelf, it's definitely worth flicking through.


1 see also Joel Spolsky's article on how Hungarian notation went wrong.