Debugging Strategies

IB Syllabus: B2.1.4 - Describe and apply debugging strategies: print statements, trace tables, breakpoints.


Key Concepts

Debugging is the process of finding and fixing errors (bugs) in a program. There are three main types of errors:

Error Type When it happens Example
Syntax error At compile time Missing semicolons, mismatched braces (Python: missing colons, bad indentation)
Runtime error During execution Division by zero, array index out of bounds
Logic error Program runs but gives wrong results Using < instead of <=, wrong formula

Logic errors are the hardest to find because the program compiles and runs without crashing - it just produces incorrect results. The strategies below help you track them down.


Strategy 1: Print Statements

Add System.out.println() (Python: print()) at key points to inspect variable values during execution.

Example - Finding a Logic Error

This code should find the average of an array, but gives the wrong answer:

int[] scores = {80, 90, 70, 85, 95};
int sum = 0;

for (int i = 0; i <= scores.length; i++) {   // Bug here!
    sum += scores[i];
}

double average = sum / scores.length;          // Bug here too!
System.out.println("Average: " + average);
scores = [80, 90, 70, 85, 95]
total = 0      # "sum" is a built-in function name in Python, so we use total

for i in range(len(scores) + 1):     # Bug here! (the twin of Java's <=)
    total = total + scores[i]

average = total // len(scores)       # Bug here too! (// floors the answer)
print("Average:", average)

Add print statements to investigate:

int[] scores = {80, 90, 70, 85, 95};
int sum = 0;

for (int i = 0; i <= scores.length; i++) {
    System.out.println("i = " + i);            // DEBUG
    System.out.println("scores[i] = " + scores[i]);  // DEBUG
    sum += scores[i];
    System.out.println("sum = " + sum);        // DEBUG
}

System.out.println("Final sum: " + sum);       // DEBUG
double average = sum / scores.length;
System.out.println("Average: " + average);
scores = [80, 90, 70, 85, 95]
total = 0

for i in range(len(scores) + 1):
    print("i =", i)                        # DEBUG
    print("scores[i] =", scores[i])        # DEBUG
    total = total + scores[i]
    print("total =", total)                # DEBUG

print("Final total:", total)               # DEBUG
average = total // len(scores)
print("Average:", average)

Running this reveals:

  • i reaches 5, causing ArrayIndexOutOfBoundsException → fix <= to <
  • sum / scores.length uses integer division → fix to (double) sum / scores.length

(Python twin: i reaches 5 and raises IndexError → fix range(len(scores) + 1) to range(len(scores)); // floors the average → use /.)

After fixing bugs, remove the debug print statements before submitting your code.


Strategy 2: Trace Tables

A trace table tracks the value of every variable after each line executes. This is a required skill for IB Paper 2.

Example - Manual Trace

int x = 5;
int y = 3;
int z = x + y;
x = z * 2;
y = x - z;
x = 5
y = 3
z = x + y
x = z * 2
y = x - z
Line x y z
int x = 5 5 - -
int y = 3 5 3 -
int z = x + y 5 3 8
x = z * 2 16 3 8
y = x - z 16 8 8

Example - Tracing a Loop

int total = 0;
for (int i = 1; i <= 4; i++) {
    total += i;
}
total = 0
for i in range(1, 5):
    total = total + i
Iteration i total (after body)
1 1 1
2 2 3
3 3 6
4 4 10

When tracing loops: write the loop variable first, then compute each expression using the current values. After the body runs, record the updated values.


Strategy 3: Breakpoints and Step-Through

In an IDE (like BlueJ, IntelliJ, or VS Code), you can:

  1. Set a breakpoint - click the line number to mark where execution should pause
  2. Run in debug mode - the program runs until it hits the breakpoint
  3. Step through - execute one line at a time and inspect variable values
  4. Watch variables - see values update in real-time as you step
Action What it does
Breakpoint Pauses execution at a specific line
Step Over Execute current line, move to next
Step Into Enter a method call to trace inside it
Continue Run until the next breakpoint or end

In IB exams, you won’t have an IDE. Practice using trace tables on paper - they are the exam-equivalent of breakpoints.


Common Bug Patterns

Off-by-one Errors

// Bug: <= causes ArrayIndexOutOfBoundsException
for (int i = 0; i <= arr.length; i++) {  // should be <

// Bug: starts at 1, skips first element
for (int i = 1; i < arr.length; i++) {   // should start at 0

// Bug: misses last element
for (int i = 0; i < arr.length - 1; i++) {  // should be < arr.length
# Bug: the + 1 causes IndexError on the last pass
for i in range(len(arr) + 1):     # should be range(len(arr))

# Bug: starts at 1, skips the first element
for i in range(1, len(arr)):      # should start at 0

# Bug: misses the last element
for i in range(len(arr) - 1):     # should be range(len(arr))

Integer Division

int a = 7, b = 2;
double result = a / b;     // Bug: result is 3.0, not 3.5
double result = (double) a / b;  // Fix: cast to double first
a = 7
b = 2
result = a // b    # Bug (Python version): // floors the answer - 3, not 3.5
result = a / b     # Fix: / always gives the decimal answer, no cast needed

Confusing = and ==

if (x = 5) { ... }    // Bug: assignment, not comparison
if (x == 5) { ... }   // Fix: use ==
if x = 5:     # Bug: assignment, not comparison - Python refuses to run this (SyntaxError)
if x == 5:    # Fix: use ==

String Comparison with ==

if (name == "Alice") { ... }       // Bug: compares references
if (name.equals("Alice")) { ... }  // Fix: compares content
# Python: == compares string CONTENT, so it is the correct choice here
if name == "Alice":     # correct in Python - there is no .equals()

Quick Code Check

Q1. A program compiles and runs but produces the wrong output. What type of error is this?

Q2. What is the purpose of a trace table?

Q3. What is wrong with for (int i = 0; i <= arr.length; i++)?

Q4. What does a breakpoint do in an IDE?


Trace Exercise

Trace this code - fill in the value of each variable after each line.

int a = 12;
int b = 5;
int c = a % b;
a = a - c;
b = a / b;
a = 12
b = 5
c = a % b
a = a - c
b = a // b    # Java's whole-number division - Python needs //
Lineabc
int a = 12 - -
int b = 5 12 -
int c = a % b 12 5
a = a - c 5 2
b = a / b 10 2

Trace Exercise 2 - Find the Bug

This code should print the sum of 1 to 5 (expected: 15). Trace it to find the bug.

int sum = 0;
for (int i = 0; i < 5; i++) {
    sum += i;
}
System.out.println("Sum: " + sum);
total = 0      # "sum" is a built-in function name in Python, so we use total
for i in range(0, 5):
    total = total + i
print("Sum:", total)
Iterationisum after body
1
2
3
4
5

Output prints:

Bug: the loop adds instead of 1+2+3+4+5. Fix: change i = 0; i < 5 to i = 1; i <= 5.


Spot the Bug

This code should find the largest number in an array by comparing each element against a running maximum, but it initializes the maximum incorrectly. This tests a common debugging pattern: choosing the right initial value for accumulator variables. Find the bug.

int[] nums = {3, 7, 2, 9, 5};
int max = 0;
for (int i = 0; i < nums.length; i++) {
    if (nums[i] > max) {
        max = nums[i];
    }
}

What is wrong and how do you fix it?


Practice Exercises

Core

  1. Trace practice - Complete a trace table for this code:
    int a = 8;
    int b = 3;
    int c = a / b;
    a = a % b;
    b = c + a;
    
    a = 8
    b = 3
    c = a // b
    a = a % b
    b = c + a
    
  2. Find the bug - This code should print numbers 1 to 10 but doesn’t work correctly. Find and fix the bug:
    for (int i = 1; i < 10; i++) {
        System.out.println(i);
    }
    
    for i in range(1, 10):
        print(i)
    
  3. Add debug prints - Given a program that calculates the average of an array, add print statements to track i, arr[i], and sum at each iteration.

Extension

  1. Trace a nested loop - Trace this code and write the complete output:
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= i; j++) {
            System.out.print(i * j + " ");
        }
        System.out.println();
    }
    
    for i in range(1, 4):
        for j in range(1, i + 1):
            print(i * j, end=" ")
        print()
    
  2. Fix three bugs - This program has three different bugs (syntax, runtime, and logic). Find and fix all three:
    int[] data = {10, 20, 30, 40, 50}
    int sum = 0;
    for (int i = 0; i <= data.length; i++) {
        sum += data[i];
    }
    double avg = sum / data.length;
    System.out.println("Average: " + avg);
    

In-Class Practice

Debugging is a skill you build by running and inspecting code, not by submitting answers to an autograder. Work through the Practice Exercises above using BlueJ or VSCode:

  • Set breakpoints, step through, and watch variables change line by line (Ex 1, Ex 4 trace tables).
  • Run buggy code, observe the wrong output or stack trace, and use the debugger or print statements to localise the fault before fixing it (Ex 2, Ex 5).
  • Add print statements to track variable values across iterations (Ex 3): the act of choosing what to print is the lesson.

No autograded GitHub Classroom assignment for this topic: debugging works best live with your teacher or in your own editor.


Connections

Prerequisites:

Related Topics:

  • Iteration - loops are a common source of off-by-one errors
  • 1D Arrays - array bounds errors are frequent bugs

Trace tables are one of the most important exam skills. Practice them regularly - being able to manually trace any code is the foundation of understanding algorithms.


© EduCS.me — A resource hub for Computer Science education

This site uses Just the Docs, a documentation theme for Jekyll.