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:
ireaches 5, causingArrayIndexOutOfBoundsException→ fix<=to<sum / scores.lengthuses 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:
- Set a breakpoint - click the line number to mark where execution should pause
- Run in debug mode - the program runs until it hits the breakpoint
- Step through - execute one line at a time and inspect variable values
- 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 //
| Line | a | b | c |
|---|---|---|---|
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)
| Iteration | i | sum 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
- 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 - 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) - Add debug prints - Given a program that calculates the average of an array, add print statements to track
i,arr[i], andsumat each iteration.
Extension
- 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() - 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:
- Variables & Data Types - understanding variable values
- Exception Handling - runtime errors are a type of bug
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.