|
|
|
Writing Bug-Free C Code
A Programming Style That Automatically Detects Bugs in C Code
by Jerry Jongerius / January 1995
|
|
|
|
Preface
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.
Acknowledgments
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-2009 Jerry Jongerius
This book was previously published by Person Education, Inc.,
formerly known as Prentice Hall. ISBN: 0-13-183898-9
|
|