Know thy enemy
As software developers we deal with bugs all the time. We know one when we see one, right? Is there any value, then, in looking at all of the different kinds of information that comprise a software bug? Since we spend so much time preventing, identifying, and correcting bugs I think it is valuable to spend a bit of time to think about the component parts of a bug. If we do, then we may find ourselves talking and reasoning more precisely about how to approach debugging, about the effort that goes into debugging, and how to plan our processes and procedures so that as individuals or teams we can be more effective at creating bug-free software.
In the first part of this blog, I’ll discuss the components of a bug up to identifying the actual defect. Next time, I’ll explain what happens after this step, including the problem resolution.
The bugs generally have the following features:
Sighting – The sighting is the event that lets you know that the bug exists; it could be a test failure, a customer report of a problem, a crash, or a hang. The information that is captured when the bug is first sighted is almost always insufficient to know very much about the cause or behavior of the defect itself.
Symptom – The symptom is the specific way the program isn’t behaving as expected. I think of it as “the program should do X and instead it does Y.” It is more specific than the sighting because often when a program first fails the person who makes the sighting isn’t paying attention to it at a level to give a clear symptom. So it may take trying it two or three times before the symptom becomes clear.
Reproducer – This is the set of steps necessary for an arbitrary user to reproduce the symptom with at least some probability. It can include manual inputs and settings, data files or database contents, or configuration details.
Description – The description is the full write up of the bug and it should include the symptom as well as some kind of articulation of the context in which the symptom can be seen. If a full reproducer is available then including that is ideal. Usually the more precise the information the better but in practice, sometimes less than perfect bug descriptions are what you work with. The description often starts with minimal information and gets more precise as more is learned.
Failure – This is usually related to the part of the program that is responsible for doing what the program does when the symptom occurs. A program may, for example, crash because it dereferences an invalid memory address. Often it isn’t too hard to find the failure part of a bug — but then you start looking for the cause (where did the invalid address come from?)
Cause – Effect Chain – There may be one or more steps of cause -> effect that separate the initial defect in the code from the final failure that lead to the symptom.
Defect – This is the actual mistake in the program itself. It is the cause at the beginning of the effect chain. Sometimes it is a single line, word, or even character. Generally this can only be determined through a process of analyzing the behavior of the program to find each link in the cause – effect chain.
So there we have the anatomy of a bug up until the defect. Join me next time as we dig deeper into why the defect occurred and the problem resolution steps that come after it.
For more information on the tools and techniques that simplify and assist with the debugging process, visit www.roguewave.com.
• Watch this video to learn about debugging numerical simulations on accelerated architectures.
• Read this datasheet to learn more about TotalView, a scalable and intuitive debugger for parallel applications written in C, C++, and Fortran.