Writing Bug-Free C Code
A Programming Style That Automatically Detects Bugs in C Code
by Jerry Jongerius / January 1995
<< Previous Index Next >>

Quick Overview of the Book
How It All Started
  Contacting the Author

This book describes an alternate class methodology that provides complete data hiding and fault-tolerant run-time type checking of objects in C programs. With it, you will produce code that contains fewer bugs.

The class methodology helps to prevent bugs by making it easier to write C code. It does this by eliminating data structures (class declarations) from include files, which makes a project easier to understand (because there is not as much global information), which makes it easier to write C code, which helps to eliminate bugs. This class methodology, which uses private class declarations, is different from C++, which uses public class declarations.

The class methodology helps detect bugs by providing for both compile-time and run-time type checking of pointers (handles) to class objects. This run-time type checking catches a lot of bugs for you since invalid object handles (the cause of a lot of bugs) are automatically detected and reported.

We have all, at some point in our programming careers, spent several hours or days tracking down a particularly obscure bug in our code. Have you ever stepped back and wondered how following a different programming methodology might have prevented such a bug from occurring or have automatically detected it? Or have you tracked down the same type of bug several times?
The key to eliminating bugs from your code is learning from your mistakes.
I have had my fair share of bugs, but when one does occur, I immediately try to institute a new programming methodology that helps prevent and/or automatically detect the bug. That is what this book is all about. It documents the techniques that I use to write virtually bug-free code. You may not agree with 100 percent of the techniques I use and that is OK and only fair, since every programmer has his or her own style. Where you do disagree, however, I challenge and urge you to come up with an alternate methodology that works for you.

Quick Overview of the Book

The examples in this book were taken directly from a large production Windows application. Because of this, some of the names you will find are tied to the environment in which the program resides. However, I prefer to show you code taken directly from a real-life production application rather than code that has been made up simply because this book is being written.

"Understand Why Bugs Exist." Chapter 1 explores why I think bugs exist in programs today. This is the first step in writing bug-free code. How can we hope to eliminate bugs from our code unless we understand how they come to exist?

"Know Your Environment." In order to implement your own programming methodologies that detect bugs, it is important to fully understand your programming environment. Chapter 2 examines the C language and preprocessor in an attempt to show you something new about your programming environment, even if you have been programming in C for many years. For example, did you know that buffer[nIndex] is equivalent to nIndex[buffer]? Chapter 2 also contains a few programming puzzles to get you thinking about your programming environment.

"Rock-Solid Base." Chapter 3 stresses the importance of coding upon a rock-solid base. Without a bug-free base to code upon, how can you be expected to write bug-free code? Chapter 3 suggests what should be done.

"The Class Methodology." The class methodology is the key to writing bug-free code and is described in Chapter 4. The class methodology allows complete data hiding and fault-tolerant run-time type checking of objects in C. It accomplishes complete data hiding by moving data declarations out of include files and into the one source file that needs the declaration (very much unlike the public class declarations in C++). The breakthrough to this class methodology is that pointers (handles) to objects of a class can be type checked by the compiler in other source files that use the class but do not have access to the data declaration.

"A New Heap Manager." The heap manager that comes with C does not detect programmer bugs. Chapter 5 shows how to create a heap manager that is rock-solid. In addition, the heap manager is needed to support the class methodology.

"Designing Modules." Now that everything is in place for writing bug-free code, how should a module be designed? Chapter 6 shows that the key to designing and coding modules is to always code what to do, not how to do it.

"General Tips." Chapter 7 contains a variety of tips for writing bug-free code. For example, a key to writing bug-free code is learning from your mistakes. Also, designing stack trace support into an application allows you to track down problems without having to reproduce the problem.

"Style Guide." Chapter 8 describes the style that I use to write C code. While every programmer has his or her own way of coding, I feel it is important that a style guide exist in written form.

"Conclusion." Chapter 9 contains concluding remarks. The class methodology and run-time type checking are key features presented in this book.

"Code Listings." This appendix brings together all the code presented in the book into one convenient location.

How It All Started

It all started when I was a sophomore in high school. Back then, I was introduced to an Apple II computer and was completely amazed by what the computer could do. The Apple had great graphics with plenty of games and educational software. I began to wonder how all the magic was accomplished.

It wasn't long before I wrote my first BASIC program. Shortly thereafter, however, I encountered my first bug. The only tools and resources available were the computer, the computer manuals and myself. Those were trying times. It taught me to think things through before jumping into coding.

In my probing around into how the computer worked, I quickly came across something called assembly language and the command CALL -151 (the equivalent of DEBUG for the PC, but in the Apple II ROM). The speed at which programs executed in relation to BASIC was remarkable. At that time, all my assembly language programming was done by hand. The assembly program was entered by typing in the hex digits of the opcode and operands. To this day I still remember a lot of opcodes even though I have not coded in 6502 assembly for many years. I quickly realized the benefits of designing a piece of code before writing it because making any changes essentially meant rewriting the entire assembly program. Later, I purchased an assembler.

My quest for finding out how the computer worked has never ended. I disassembled (reverse engineered) and commented the entire Apple II Disk Operating System (DOS 3.3 at that time), the bootstrap ROMs and parts of the BASIC interpreter ROMs. I started writing programs that performed disk protection, added keyboard buffers, and so on -- in other words, systems programming.

Today, I am working on an 80486 66-MHz DX2 with 32 megabytes of memory, local bus video and 600 megabytes of hard disk space -- quite a change from a 1-MHz, 64 kilobytes of memory, 140-kilobyte floppy disk drive Apple II. The hardware has changed drastically, but the methodologies used to write programs haven't changed as fast. The quality of code certainly hasn't improved by several orders of magnitude.

After college, I started working at Datametrics Systems Corporation, a firm specializing in the performance of Unisys mainframes. Their goal was to produce a top-of-the-line performance monitoring package that ran under Microsoft Windows. A year later, that goal was realized with the release of ViewPoint 1.0. ViewPoint as it stands today is now approximately a quarter million lines of code and very stable.

ViewPoint originally started out under Windows 1.0. Shortly thereafter, Windows 2.0 was released. Since then, Windows 3.0 and now Windows 3.1 have become mega hits in the PC industry.

The great thing about Windows 3.0 was that programming bugs could be caught much quicker than before because programming errors caused a general protection fault instead of just trashing memory and more than likely hanging the PC. This is because under pre-3.0 Windows, programs had full access to all the memory in the PC, even memory of other processes. So a bug could trash anything and usually would. Windows 3.0 supported protected address spaces. Therefore, an access to a random memory location most likely would be detected (the infamous UAE, Unrecoverable Application Error) by the operating system and your program halted.

When I converted ViewPoint to Windows 3.0, it ran the first time. The protected-mode architecture turned up no programming bugs, not a single one! In fact, the ViewPoint 1.0 binary, which was targeted to Windows 2.0, a non-protected OS, can still be run under Windows 3.1, a protected OS, without any problems. This indicates that the program contains no invalid memory references and indicated to me that the programming methodologies that were used to write ViewPoint are valid.

In the last few years, the programming industry has moved from procedural programming to object-oriented programming (OOP). However, OOP alone does not solve the underlying quality control problems facing the industry. OOP alone does not make you a better programmer.

I wrote this book to document the programming methodologies that I have used to write ViewPoint under Windows. The methodologies were designed and developed using Microsoft C5 through C8. Since the introduction of Microsoft C/C++ 7.0, the code has been ported to compile under C++.

Contacting the Author

If you have any comments on this book, I would like to hear them. I can be reached through the Internet at jerryj@duckware.com.


Special thanks to P.J. Plauger for taking the time to listen to a first-time book author. Your help is greatly appreciated and invaluable.

I would like to thank everyone at Prentice Hall who helped to make this book a reality, especially Paul W. Becker and Patti Guerrieri.

Thanks to John Kelly, the president of Datametrics Systems Corporation, for allowing me to write a book that discloses the programming techniques that I developed at Datametrics Systems Corporation.

Thanks to Jim Kelliher, who provided feedback throughout the entire book writing process. Thanks to John McGowan, who provided feedback on the class methodology. Thanks to John Dripps, who helped during the early stages.

Copyright © 1993-1995, 2002-2024 Jerry Jongerius
This book was previously published by Pearson Education, Inc.,
formerly known as Prentice Hall. ISBN: 0-13-183898-9