THE HINDU BUSINESS LINE
Financial Daily
from THE HINDU group of publications

Monday, July 23, 2001

• AGRI-BUSINESS
• COMMODITIES
• CORPORATE
• FEATURES
• LETTERS
• LIFE
• MARKETS
• MENTOR
• NEWS
• OPINION
• VARIETY
• INFO-TECH
• CATALYST
• INVESTMENT WORLD
• MONEY & BANKING
• LOGISTICS

• PAGE ONE
• INDEX
• HOME

Mentor | Next | Prev


Break the bug wall

Steve Maguire on the key to writing a bug-free code

WITH the growing complexity of software and the associated climb in bug rates, it is becoming increasingly necessary for programmers to produce bug-free code much earlier in the development cycle, before the code is first sent to testing. The key to writ ing bug-free code is to become more aware of how bugs come about. Programmers can cultivate this awareness by asking themselves two simple questions about every bug they encounter. ``How could I have prevented this bug?'' and ``How could I have automatic ally detected this bug?''

A hypothetical compiler: If your compiler could detect every bug in your program -- no matter the type -- and issue an error message, ridding your code of bugs would be simple. Such omniscient compilers do not exist, but by enabling optional compiler war nings, using syntax and portability checkers, and using automated unit tests, you can increase the number of bugs that are detected for you automatically.

Assert yourself: A good development strategy is to maintain two versions of your program: one that you ship and one that you use to debug the code. By using debugging assertion statements, you can detect bugs caused by bad function arguments, accidental use of undefined behaviour, mistaken assumptions made by other programmers, and impossible conditions that nevertheless somehow show up. Debug -- only backup algorithms help verify function results and the algorithms used in functions.

Fortify your subsystems: Assertions wait quietly until bugs show up. Even more powerful are sub-system integrity checks that actively validate subsystems and alert you to bugs before the bugs affect the program. The integrity checks for the standard C me mory manager can detect dangling pointers, lost memory blocks, and illegal use of memory that has not been initialised or that has already been released. Integrity checks can also be used to eliminate rare behaviour, which is responsible for untested sce narios, and to force subsystem bugs to be reproducible so that they can be tracked down and fixed.

Step through your code: The best way to find bugs is to step through all new code in a debugger. By stepping through each instruction with your focus on the data flow, you can quickly detect problems in your expressions and algorithms. Keeping the focus on the data, not the instructions, gives you a second, very different, view of the code. Stepping through code takes time, but not nearly as much as most programmers would expect it to.

Candy-machine interfaces: It's not enough that your functions are bug-free; functions must be easy to use without introducing unexpected bugs. If bug rates are to be reduced, each function needs to have one well-defined purpose, to have explicit single-p urpose inputs and outputs, to be readable at the point where it is called, and ideally to never return an error condition. Functions with these attributes are easy to validate using assertions and debug code, and they minimise the amount of error handlin g code that must be written.

Risky business: Given the numerous implementation possibilities for a given function, it should come as no surprise that some implementations will be more error-prone than others. The key to writing robust functions is to exchange risky algorithms and la nguage idioms for alternatives that have proven to be comparably efficient yet much safer. At one extreme this can mean using unambiguous data types; at the other it can mean tossing out an entire design simply because it would be difficult, or impossibl e, to test.

Treacheries of the trade: Some programming practices are so risky they should never be used. Most such practices are obviously risky, but some seem quite safe, even desirable, because they fill a need without apparent hazard. These treacherous coding pra ctices are the wolves in sheep's clothing. Why shouldn't you reference memory you've just released? Why is it risky to pass data in global or static storage? Why should you avoid parasitic functions? Why it is unwise to rely on every nit-picky detail out lined in the ANSI standard?

The rest is attitude: A programmer can follow every guideline, but without the proper attitude and a set of good programming habits, writing bug-free code will be much harder than it needs to be. If a programmer believes that a bug can simply ``go away,' ' or that fixing bugs `later' won't be harmful to the product, bugs will persist. If a programmer regularly ``cleans up'' code, allows unnecessary flexibility in functions, welcomes every `free' feature that pops out of a design, or simply `tries' haphaz ard solutions to problems hoping to hit upon something that works, writing bug-free code will be an uphill battle. Having a good set of habits and attitudes is possibly the most important requirement for consistently writing bug-free code.

(Edited extracts fromWriting solid code: Microsoft's techniques for developing bug-free C programs. Book courtesy: Word Power, Chennai. e-mail: wpch@satyam.net.in)

Comment on this article to BLFeedback@thehindu.co.in

Send this article to Friends by E-Mail


Next: Amalgamation and AA
Prev: Stopwatch technique
Mentor

Agri-Business | Commodities | Corporate | Features | Letters | Life | Markets | Mentor | News | Opinion | Variety | Info-Tech | Catalyst | Investment World | Money & Banking | Logistics |

Page One | Index | Home


Copyrights © 2001 The Hindu Business Line.

Republication or redissemination of the contents of this screen are expressly prohibited without the written consent of The Hindu Business Line.