Debugging Your Programs

Copyright © 2013 Bart Massey
(Slides originally from PSU CS 161 Winter 2013.)

What is debugging?

  • During/after coding, before/during/after testing

  • Bring the program to a state where it appears to be bug-free (but this is a lie)

  • Estimate 20-40% of programming effort

  • "Secret": No good books, no chapter in our book, nothin'

    How to debug

  • Given a failure of the software:

    • Find the causes ("faults") leading to that failure
    • Find the root causes of those faults
    • Figure out and apply a repair
    • Check the repair

      • Does it fix the failures?
      • Does it cause new failures?

        Key activity: diagnosis

  • Like in medicine or car repair: "It doesn't work; what's happening and what can be done?"

  • Diagnosis is hypothesis formation and testing

    • What possible reasons might there be for observed symptoms?
    • Can those reasons be ruled out by what is known so far?
    • If not, can we do tests to rule each reason out or increase our belief that it is the correct one?
    • Repeat until exactly one possible reason remains, and it looks really likely to be true.

      Common bugs

  • Two basic kinds:

    • Bad control flow
    • Just plain calculating the wrong thing
  • Examples

    • Off-by-one "fencepost" errors
    • Copy-and-paste calculation errors
    • Typos/"Thinkos"
    • Failure to design to the spec
    • Failure to understand/implement the design

      Root Cause Analysis

  • It's not enough to find the line of code that "causes the bug"

  • You want to find out how that line got there

  • In software, faults are caused by mistakes ("errors") that were made by a human (usually you)

  • With the "root causes" found, you can:

    • Correct all the faults caused by that error
    • Take steps to make that error less likely in the future

      Preparing code for debugging

  • "Real programmers don't comment. It was hard to write--it should be hard to read and harder to understand."

  • Code should have a spec, simple tests, and pseudocode

  • Formatting should be as clean as possible

    • Consistent indentation
    • Consistent liberal use of whitespace
    • Good names
    • Idiomatic
  • Code should be instrumented appropriately

    Debugging pre-inspection

  • Read the code in question carefully. Look for things that are wrong or unclear

  • Explain the code to someone. Have them look at it too

  • Most bugs are easily found and fixed by inspection alone

    Debugging tools: your brain

  • Are you sure the spec and tests are correct?

  • White-box: what kinds of similar inputs might produce the same program misbehavior?

  • Black-box: what properties distinguish misbehaving inputs?

  • Is the timing as expected?

  • Are your current hypotheses consistent with everything you have observed or can observe?

    Debugging tools: print() function

  • For a specific hypothesis, stick a print() in that will either disconfirm or confirm the hypothesis

    • Works in a huge variety of situations
    • But don't spam instrumentation everywhere, or you will get confused by it
  • Can use print() for exploring program behavior ("tracing"), but beware: one can waste a lot of time doing this without learning anything.

  • Always best to know what the question is before you start looking for the answer

    Debugging tools: "debugger"

  • Idle will happily provide you the ability to

    • Step through your program one statement at a time
    • Run until a given program line is reached
    • Examine/change variable values anytime stopped
  • Except the debugger is really fragile and hard to use

  • In particular, doesn't interact well with input()

  • In general, debugger is tool of last resort

    Post-diagnosis

  • Once you've found the immediate source of a bug, do RCA

  • Look for other places where faults may have been inserted due to the same root causes

  • Think hard about how those faults got there. What are you going to do to avoid this in the future?

  • Craft fixes that fix the faults properly

    • This may involve changing the design or revising the specification
  • Apply the fixes, then test everything carefully

    • Did the problem get fixed?
    • Are there new problems?

      Backups, versions and source code management

  • It is really easy to get the buggy version and the fixed version and the version you are working on right now mixed up

  • Tool called source code management system helps here

  • It is probably a mistake to have too many backup files around; in any case, use a consistent clear naming scheme for backup files

    Parting thoughts

  • Don't get stuck!

    • Interrupt yourself every few minutes and see if you're making real progress
    • If you are stuck, many strategies are available:
      • Try a different approach
      • Take a break
      • Ask for help
  • Don't get discouraged

    • The most experience programmers still make a lot of bugs and have a hard time fixing them

    • The bugs you will make are all fixable