Why Programs Fail

Why Programs Fail

A Guide to Systematic Debugging

1st Edition - October 11, 2005
There is a Newer Edition Available
  • Author: Andreas Zeller
  • eBook ISBN: 9780080481739

Purchase options

Purchase options
DRM-free (PDF)
Sales tax will be calculated at check-out

Institutional Subscription

Free Global Shipping
No minimum order


Why Programs Fail is about bugs in computer programs, how to find them, how to reproduce them, and how to fix them in such a way that they do not occur anymore. This is the first comprehensive book on systematic debugging and covers a wide range of tools and techniques ranging from hands-on observation to fully automated diagnoses, and includes instructions for building automated debuggers. This discussion is built upon a solid theory of how failures occur, rather than relying on seat-of-the-pants techniques, which are of little help with large software systems or to those learning to program. The author, Andreas Zeller, is well known in the programming community for creating the GNU Data Display Debugger (DDD), a tool that visualizes the data structures of a program while it is running.

Key Features

  • Winner of a 2006 Jolt Productivity Award for Technical Books
  • Shows how to reproduce software failures faithfully, how to isolate what is important about the failure, and to discover what caused it
  • Describes how to fix the program in the best possible way, and shows how to create your own automated debugging tools
  • Includes exercises and extensive references for further study


Software developers.

Table of Contents

  • About the Author

    1 How Failures Come to Be
    1.1 My Program Does Not Work!
    1.2 From Defects to Failures
    1.3 Lost in Time and Space
    1.4 From Failures to Fixes
    1.5 Automated Debugging Techniques
    1.6 Bugs, Faults, or Defects?
    1.7 Concepts
    1.8 Tools
    1.9 Further Reading
    1.10 Exercises

    2 Tracking Problems
    2.1 Oh! All These Problems
    2.2 Reporting Problems
    2.3 Managing Problems
    2.4 Classifying Problems
    2.4.1 Severity
    2.4.2 Priority
    2.4.3 Identifier
    2.4.5 Notification
    2.5 Processing Problems
    2.6 Managing Problem Tracking
    2.7 Requirements as Problems
    2.8 Managing Duplicates
    2.9 Relating Problems and Fixes
    2.10 Relating Problems and Tests
    2.11 Concepts
    2.12 Tools
    2.13 Further Reading
    2.14 Exercises

    3 Making Programs Fail
    3.1 Testing for Debugging
    3.2 Controlling the Program
    3.3 Testing at the Presentation Layer
    3.3.1 Low-level Interaction
    3.3.2 System-level Interaction
    3.3.3 Higher-level Interaction
    3.3.4 Assessing Test Results
    3.4 Testing at the Functionality Layer
    3.5 Testing at the Unit Layer
    3.6 Isolating Units
    3.7 Designing for Debugging
    3.8 Preventing Unknown Problems
    3.9 Concepts
    3.10 Tools
    Other scripting languages
    Virtual PC
    3.11 Further Reading
    3.12 Exercises

    4 Reproducing Problems
    4.1 The First Task in Debugging
    4.2 Reproducing the Problem Environment
    4.3 Reproducing Program Execution
    4.3.1 Reproducing Data
    4.3.2 Reproducing User Interaction
    4.3.3 Reproducing Communications
    4.3.4 Reproducing Time
    4.3.5 Reproducing Randomness
    4.3.6 Reproducing Operating Environments
    4.3.7 Reproducing Schedules
    4.3.8 Physical Influences
    4.3.9 Effects of Debugging Tools
    4.4 Reproducing System Interaction
    4.5 Focusing on Units
    4.5.1 Setting Up a Control Layer
    4.5.2 A Control Example
    4.5.3 Mock Objects
    4.5.4 Controlling More Interaction
    4.6 Concepts
    4.7 Tools
    Checkpointing Tools
    4.8 Further Reading
    4.9 Exercises

    5 Simplifying Problems
    5.1 Simplifying the Problem
    5.2 The Gecko BugAThon
    5.3 Manual Simplification
    5.4 Automatic Simplification
    5.5 A Simplification Algorithm
    5.6 Simplifying User Interaction
    5.7 Random Input Simplified
    5.8 Simplifying Faster
    5.8.1 Caching
    5.8.2 Stop Early
    5.8.3 Syntactic Simplification
    5.8.4 Isolate Differences, Not Circumstances
    5.9 Concepts
    5.10 Tools
    Delta Debugging
    Simplification Library
    5.11 Further Reading
    5.12 Exercises

    6 Scientific Debugging
    6.1 How to Become a Debugging Guru
    6.2 The Scientific Method
    6.3 Applying the Scientific Method
    6.3.1 Debugging sample—Preparation
    6.3.2 Debugging sample—Hypothesis
    6.3.3 Debugging sample—Hypothesis
    6.3.4 Debugging sample—Hypothesis
    6.3.5 Debugging sample—Hypothesis
    6.4 Explicit Debugging
    6.5 Keeping a Logbook
    6.6 Debugging Quick-and-Dirty
    6.7 Algorithmic Debugging
    6.8 Deriving a Hypothesis
    6.9 Reasoning About Programs
    6.10 Concepts
    6.11 Further Reading
    6.12 Exercises

    7 Deducing Errors
    7.1 Isolating Value Origins
    7.2 Understanding Control Flow
    7.3 Tracking Dependences
    7.3.1 Effects of Statements
    7.3.2 Affected Statements
    7.3.3 Statement Dependences
    7.3.4 Following Dependences
    7.3.5 Leveraging Dependences
    7.4 Slicing Programs
    7.4.1 Forward Slices
    7.4.2 Backward Slices
    7.4.3 Slice Operations
    7.4.4 Leveraging Slices
    7.4.5 Executable Slices
    7.5 Deducing Code Smells
    7.6 Limits of Static Analysis
    7.7 Concepts
    7.8 Tools
    7.9 Further Reading
    7.10 Exercises

    8 Observing Facts
    8.1 Observing State
    8.2 Logging Execution
    8.2.1 Logging Functions
    8.2.2 Logging Frameworks
    8.2.3 Logging with Aspects
    8.2.4 Logging at the Binary Level
    8.3 Using Debuggers
    8.3.1 A Debugging Session
    8.3.2 Controlling Execution
    8.3.3 Postmortem Debugging
    8.3.4 Logging Data
    8.3.5 Invoking Functions
    8.3.6 Fix and Continue
    8.3.7 Embedded Debuggers
    8.3.8 Debugger Caveats
    8.4 Querying Events
    8.4.1 Watchpoints
    8.4.2 Uniform Event Queries
    8.5 Visualizing State
    8.6 Concepts
    8.7 Tools
    8.8 Further Reading
    8.9 Exercises

    9 Tracking Origins
    9.1 Reasoning Backwards
    9.2 Exploring Execution History
    9.3 Dynamic Slicing
    9.4 Leveraging Origins
    9.5 Tracking Down Infections
    9.6 Concepts
    9.7 Tools
    9.8 Further Reading
    9.9 Exercises

    10 Asserting Expectations
    10.1 Automating Observation
    10.2 Basic Assertions
    10.3 Asserting Invariants
    10.4 Asserting Correctness
    10.5 Assertions as Specifications
    10.6 From Assertions to Verification
    10.7 Reference Runs
    10.8 System Assertions
    10.8.1 Validating the Heap with MALLOC_CHECK
    10.8.2 Avoiding Buffer Overflows with ELECTRICFENCE
    10.8.3 Detecting Memory Errors with VALGRIND
    10.8.4 Language Extensions
    10.9 Checking Production Code
    10.10 Concepts
    10.11 Tools
    10.12 Further Reading
    10.13 Exercises

    11 Detecting Anomalies
    11.1 Capturing Normal Behavior
    11.2 Comparing Coverage
    11.3 Statistical Debugging
    11.4 Collecting Data in the Field
    11.5 Dynamic Invariants
    11.6 Invariants on the Fly
    11.7 From Anomalies to Defects
    11.8 Concepts
    11.9 Tools
    11.10 Further Reading
    11.11 Exercises

    12 Causes and Effects
    12.1 Causes and Alternate Worlds
    12.2 Verifying Causes
    12.3 Causality in Practice
    12.4 Finding Actual Causes
    12.5 Narrowing Down Causes
    12.6 A Narrowing Example
    12.7 The Common Context
    12.8 Causes in Debugging
    12.9 Concepts
    12.10 Further Reading
    12.11 Exercises

    13 Isolating Failure Causes
    13.1 Isolating Causes Automatically
    13.2 Isolating versus Simplifying
    13.3 An Isolation Algorithm
    13.4 Implementing Isolation
    13.5 Isolating Failure-inducing Input
    13.6 Isolating Failure-inducing Schedules
    13.7 Isolating Failure-inducing Changes
    13.8 Problems and Limitations
    13.9 Concepts
    13.10 Tools
    Delta Debugging Plug-ins for ECLIPSE
    13.11 Further Reading
    13.12 Exercises

    14 Isolating Cause-Effect Chains
    14.1 Useless Causes
    14.2 Capturing Program States
    14.3 Comparing Program States
    14.4 Isolating Relevant Program States
    14.5 Isolating Cause-Effect Chains
    14.6 Isolating Failure-inducing Code
    14.7 Issues and Risks
    14.8 Concepts
    14.9 Tools
    14.10 Further Reading
    14.11 Exercises

    15 Fixing the Defect
    15.1 Locating the Defect
    15.2 Focusing on the Most Likely Errors
    15.3 Validating the Defect
    15.3.1 Does the Error Cause the Failure?
    15.3.2 Is the Cause Really an Error?
    15.3.3 Think Before You Code
    The Devil’s Guide to Debugging
    15.4 Correcting the Defect
    15.4.1 Does the Failure No Longer Occur?
    15.4.2 Did the Correction Introduce New Problems?
    15.4.3 Was the Same Mistake Made Elsewhere?
    15.4.4 Did I Do My Homework?
    15.5 Workarounds
    15.6 Learning from Mistakes
    15.7 Concepts
    15.8 Further Reading
    15.9 Exercises

    Appendix: Formal Definitions
    A.1 Delta Debugging
    A.1.1 Configurations
    A.2 Passing and Failing Run
    A.3 Tests
    A.4 Minimality
    A.5 Simplifying
    A.6 Differences
    A.7 Isolating
    A.2 Memory Graphs
    A.2.1 Formal Structure
    A.2.2 Unfolding Data Structures
    A.2.3 Matching Vertices and Edges
    A.2.4 Computing the Common Subgraph
    A.2.5 Computing Graph Differences
    A.2.6 Applying Partial State Changes
    A.2.7 Capturing C State
    A.3 Cause-Effect Chains


Product details

  • No. of pages: 480
  • Language: English
  • Copyright: © Morgan Kaufmann 2005
  • Published: October 11, 2005
  • Imprint: Morgan Kaufmann
  • eBook ISBN: 9780080481739

About the Author

Andreas Zeller

Andreas Zeller is a full professor for Software Engineering at Saarland University in Saarbruecken, Germany. His research concerns the analysis of large software systems and their development process; his students are funded by companies like Google, Microsoft, or SAP. In 2010, Zeller was inducted as Fellow of the ACM for his contributions to automated debugging and mining software archives. In 2011, he received an ERC Advanced Grant, Europe's highest and most prestigious individual research grant, for work on specification mining and test case generation. His book "Why programs fail", the "standard reference on debugging", obtained the 2006 Software Development Jolt Productivity Award.

Affiliations and Expertise

Saarland University, Saarbruecken, Germany