Robert Ward is president of R&D Publications, Inc. and author of Debugging C, an introduction to scientific debugging. He has done consulting work in software engineering and data communications and holds an M.S.C.S. from the University of Kansas.
Despite several studies that show debugging consumes more than half of a programmer's programming efforts, there is still a relative dearth of technical information about debugging. In fact Martin Stitt's new book, Debugging: Creative Techniques and Tools for Software Repair, may be the only advanced treatment currently in print. As such, it is a welcome addition to the technical literature, all the more so because it explains many advanced techniques that I've never seen explained anywhere else.
(Just so you know my bias, I wrote a somewhat less advanced debugging book several years ago. It is now out of print.)
A C programmer should be moderately comfortable reading this book, but it will help to have a sound background in 80x86 assembly language. While many examples are presented in C and nearly all of the techniques are equally useful to C and assembly language programmers, whenever faced with a sticky subject, Stitt relies on explanations based on assembly language.
Most likely, beginning programmers will find most of the central tools in this book somewhat beyond their ken. To really get all this book has to offer, you should be comfortable writing your own system calls, be very familiar with interrupts and accompanying issues like mutual exclusion and reentrancy, and be familiar with the general structure of a device driver. If you are this far, (in other words if you are ready to take a shot at writing your own device driver, TSR, or interrupt intercept), this book can leverage your knowledge into some very powerful debugging skills.
While many of the underlying ideas are generally applicable, the book is so heavily slanted toward MS-DOS/AT platforms, that it won't be very useful to programmers working in other environments.
Stitt seems to be strongly concerned about timing issues and throughout the book's examples suggests you use cryptic trace markers. While anything less than a graphic windowing environment may offend some readers, Stitt's preference is justified if you work frequently with timing-sensitive problems, and it's a trivial matter in most of his techniques to use more readable trace messages.
Stitt's book is broken into three major parts followed by a healthy spate of appendices. Part one discusses "Bug-Hunting Basics", Part Two covers the construction of tools, and Part Three covers techniques for diagnosis and the use of tools. A code disk is available separately for $32.95. As I'll explain later, if you buy the book you should plan to buy the disk also.
Stitt is clearly most comfortable with the material presented in the second and third parts. While it's clear that he understands the basics of debugging, his heart isn't in teaching them. Part One, comes across as a cursory treatment of obligatory topics, sprinkled with unexplained mentions of advanced topics. While several components of this section are very interesting for an intermediate to advanced reader, it isn't really targeted for that reader. Unfortunately, the intended target, the beginning debugger, will probably find this section somewhat frustrating.
By contrast, the second section is developed in great detail. Here Stitt presents some very interesting tools and techniques. You'll learn how to intercept interrupts so that you can monitor system calls, how to direct trace output to the ring buffer in a custom device driver, how to attach a terminal or second machine as a remote trace monitor, how to use interrupt intercepts to "pace" events in timing sensitive environments, and more. Unfortunately, while Stitt explains most of the tricks and coding issues involved, he doesn't quite give you the working code that is reserved for the code disk. In fact, if you really want to get any useful tools from this book, you must get the code disk.
From the description in the book, I'd say the code disk was a worthwhile purchase. You get a working debugging system consisting of a device driver with routing logic and ring buffer. A stand-alone user interface that can directly or remotely query and control the device driver. Also included is a package of macros that dump trace information to the driver, code to install pre-written interrupt intercepts, and templates for creating your own device drivers, TSR's, and interrupt intercepts.
When output to the debugging device driver, all trace data can be directed to a local or remote printer (parallel or serial) or just captured in the ring buffer. The driver can also "gate" the trace data, allowing you to exercise some discretion without recompiling the program under test. With some debuggers, you can even send trace data to the device without inserting marker macros in the source code (by using a breakpoint to execute a custom output routine).
Even if you don't care about improving your debugging powers, this package would be worth it just for the head start on creating a TSR, device driver, or interrupt intercept.
Part Three is devoted to diagnostic and search techniques. This is the section that works best as a teaching text. Here you'll learn interesting and effective techniques for "getting your bearings" after you've "broken" into a running program, for capturing execution history, for making effective use of a disassembler, for tracing and interpreting system calls, for simplifying the program under test, for controlling environment and input, and for chasing intermittent bugs, performance bugs, interrupt-related bugs, timing-sensitive bugs, and position sensitive bugs.
This section is notable for its advice on how to study code. Even though some Bell Labs studies suggest that expert debuggers study the code and application far more effectively than novices, I've not seen anyone outside of these researchers give any very useful advice on this topic. Stitt supplies some excellent advice about how to study the code and bug so that your later efforts will be more effective.
My main complaint about Part Three is that it's really a misplaced Part Two. In fact, I'd almost wager that Part Three was originally the second part of the book, and was later moved to satisfy some editor. In Part One, Stitt hints at the existence of certain tools; in Part Three he shows why these are needed and how they are used to find different bugs, and in Part Two he gives detailed instructions for implementing these tools. I suggest you ignore the printed order and read the sections in the correct order: One, Three, Two. It will greatly reduce the effort necessary to absorb the material in Part Two.
I would also suggest reading the Appendices out of order. The appendices span the last 100 pages of this book. In particular, you should read the "Tool and Technique Locator Chart" either as or immediately after you read Part Three. This appendix connects symptoms and types of bug with the appropriate tool and gives some very good advice about how to apply some of the tools. Along with the narrative information, this appendix supplies a list of tools appropriate to each type of bug. A table at the end of the appendix indexes those parts of the book that are germane to each type of tool. If you feel lost at some point in your reading, try using the index in this appendix to locate whatever information you are missing.
If you are not intimately familiar with MS-DOS system call conventions, you should read the "System-Level Knowledge for Debugging" before reading Section Three.
Other appendices include information about patch techniques, building parallel and serial link cables, math for address conversions, and 50 pages of macros. Unfortunately, the macros are mostly trivial, partly because they were originally designed to communicate with Stitt's sophisticated debugging driver, and partly because of his concern with fast trace transactions.
Stitt's writing is clear, readable, and packed with details. While each of these details are useful, at times, because they are dropped in the middle of an introductory explanation, they distract. The book is well produced, though I think the explanation of several of the tricky subjects (e.g., stack switching in a re-entrant environment) would benefit from some simple diagrams.
On the whole, this is a very useful book, one that makes some relatively esoteric techniques available to a much larger audience. I know few programmers who are familiar with all of these techniques. In short, you should buy it, but only if you buy the disk, too. Fortunately, the combination is well worth the price.
Book Information
Title: Debugging: Creative Techniques and Tools for Software Repair
Author: Martin Stitt
Publisher: John Wiley & Sons
1-800-CALLWILEY
Price: $32.95
ISBN: 0-471-55831-1Companion Toolset Diskette
High Density, 5 1/4
Price: $32.95
ISBN: 0-471-57537-2Book/Disk Set
Price: $65.90
ISBN: 0-471-55829-X