Debugging Strategies
IB Syllabus: B2.1.4 - Describe and apply debugging strategies: print statements, trace tables, breakpoints.
Table of Contents
- Key Concepts
- Strategy 1: Print Statements
- Strategy 2: Trace Tables
- Strategy 3: Breakpoints and Step-Through
- Common Bug Patterns
- Quick Code Check
- Trace Exercise
- Trace Exercise 2 - Find the Bug
- Spot the Bug
- Practice Exercises
- GitHub Classroom
- Connections
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 |
| 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() 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);
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);
Running this reveals:
ireaches 5, causingArrayIndexOutOfBoundsException→ fix<=to<sum / scores.lengthuses integer division → fix to(double) sum / scores.length
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;
| 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;
}
| 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
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
Confusing = and ==
if (x = 5) { ... } // Bug: assignment, not comparison
if (x == 5) { ... } // Fix: use ==
String Comparison with ==
if (name == "Alice") { ... } // Bug: compares references
if (name.equals("Alice")) { ... } // Fix: compares content
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;
| 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);
| 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; - 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); } - 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(); } - 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);
GitHub Classroom
Codespace Setup Instructions (click to expand)
First Time Setup
- Click “Open in GitHub” above, then click the green “Accept this assignment” button
- Check the email registered with your GitHub account – click the link there to open your repository. This avoids access issues and means your teacher does not need to share links manually
- Wait for your repository to be created, then click “Open in Codespace”
- Wait for the Codespace to finish loading (you’ll see VS Code in your browser)
Important: Switch to Standard Mode
- Look at the bottom status bar. If it says
Java: Lightweight Mode, click on it and select Standard - Wait for Java to finish loading (status bar will say
Java: Ready) - Without Standard Mode, the Run button won’t work and you’ll get “Main method not found” errors
Dismiss Popups
You’ll see two notification popups. Dismiss them both:
- “Would you like VS Code to periodically run git fetch?” → Click No
- “There’s a pull request associated with main” → Click Don’t Show Again
These are housekeeping popups, not part of the assignment.
How to Code
- Open
src/Debugging.java. This is the only file you need to edit - Complete each
// TODOsection - Click the Run button (▶ above
main) to test your output - Compare your output with the expected output written in the comments above each task
How to Check Your Code
You can check your work in two ways:
Option A: Run your code directly
- Click the Run button (▶) above
maininDebugging.java - Compare your printed output with the expected output shown in the comments above each task
Option B: Run the autograder tests
- Open the Terminal (Menu → Terminal → New Terminal)
- Type
bash run-tests.shand press Enter - Green ✓ = test passed, Red ✗ = test failed
- Each test tells you what it expected. Read the error message to fix your code
How to Submit
- Click the Source Control icon (branch icon) in the left sidebar
- Type a message like
completed tasksin the message box - Click the green Commit button
- If asked “stage all changes?” → click Always
- Click Sync Changes → if asked about push/pull → click OK, Don’t Show Again
- Done! Autograding runs automatically. Your teacher can see your results in the GitHub Classroom dashboard
How to Review Feedback
- Go to your repository on GitHub
- Click the “Pull requests” tab at the top
- Open the pull request called “Feedback”
- Click the “Files changed” tab. You’ll see your teacher’s comments on specific lines of your code
- Read through each comment carefully, then fix your code in Codespaces
- Run
bash run-tests.shin your Codespaces Terminal to check your fixes - Commit and push again (repeat steps 12-17). The autograder will re-run automatically
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.