Click Here!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Sams Teach Yourself Visual J++ 6 in 21 Days
(Publisher: Macmillan Computer Publishing)
Author(s): Rick Leinecker
ISBN: 0672313510
Publication Date: 11/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


Debugging Tips

Knowing the Visual J++ debugger inside and out makes it easier to debug programs. But that’s only part of what you need in order to debug Visual J++ programs. You need an approach to debugging that helps you get to the problem. You can spend hours chasing your tail trying to find a bug, but if you follow the suggestions presented next, you should better be able to avoid costly dead ends.

You can sometimes fix a bug and then find another bug related to the first or to the way you fixed it. When I fix a bug, I ask myself three questions to ensure that I’ve thought carefully about its significance. You can use these questions to improve productivity and quality every time you think you’ve found and fixed a bug.

The key idea behind these questions is that every bug is a symptom of an underlying process. You have to treat the symptoms, but if all you do is treat symptoms, you’ll continue to see more symptoms forever. You need to find out what process produced the bug and then change the process. The underlying process that caused your bug probably is nonrandom and can be controlled after you identify what happened and what caused it to happen.

Before you ask the three questions, you need to overcome your natural resistance to looking carefully at the bug. Look at the code and explain what went wrong. Start with the observable facts and work backward, asking why repeatedly, until you can describe the pattern that underlies the bug. Often, you should do this with a colleague, because explaining what you think happened will force you to confront your assumptions about what the program is up to. Here’s an example of such scrutiny:

   It blew up because subscript j was out of range.
   Why?

   j was 10 but the top array subscript is only 9.
   Why?

   j is a string length, and the array origin is 0; so the last character in a string
   of length 1 is index 0.

Look for additional surprises in the situation at the time the bug was found. Check key program variables at the point of failure to see whether you can explain their values. For example:

   Why is the name null?

   Why was it trying to output an error message anyway?

Keep notes of what you did and what happened. You need to know what is really going on, and this means keeping measurements and history.

When these steps are out of the way, you are ready to ask the first of the three questions.

Is This Mistake Somewhere Else Also?

Look for other places in the code where the same pattern applies. Vary the pattern systematically to look for similar bugs. Ask questions such as these:

   Where else do I use a length as a subscript?

   Do all my arrays have the same origin?

   What would happen for a zero length string?

Try to describe the local rule that should be true in this section of the code but that the bug disobeyed; your search for this invariant[1] will help you see other potential bugs. This is the general thought pattern:

   The starting offset plus the length, minus 1, is the ending subscript…unless???
   the length is zero.

It’s more productive to fix several bugs for every one you find. Trying to describe the bugs in general terms also raises your level of understanding about what the program is doing and helps you avoid introducing more bugs as you program.

What Next Bug Is Hidden Behind This One?

After you figure out how to fix the bug, you need to imagine what will happen after you fix it. The statement after the failing one might have a bug in it too, but the program never got that far before; or some other code might be entered for the first time as a result of your fix. Take a look at these untried statements and look for bugs in them. Think about this:

   Would this next statement work?

While you’re thinking about control flow is a good time to ask whether there are other unreached parts of the program. Ask yourself:

   Are there combinations of features I’ve never tested?

It doesn’t take much work to instrument a program so that you can check off as you execute its various parts; and it’s often surprising how much of a program doesn’t work at all after the builder says it’s been tested. The thought process continues:

   Can I make all the error messages come out in test?

Beware of making a change in one place that causes a bug somewhere else. A local change to some variable might violate the assumptions made further on in execution. For example, you might consider this:

   If I just subtract 1 from j, the move statement later will try to move -1
   characters when the string length is 0.

If you’ve made a lot of changes to the program already, consider carefully whether adding another local fix is the right thing to do, or whether it’s time to redesign and reimplement.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.