Lesson 38 of 50 intermediate

Debugging Like a Detective

Finding and fixing bugs — the skill that separates good from great!

Open interactive version (quiz + challenge)

Real-world analogy

Debugging is like being Sherlock Holmes. Your code gives the wrong answer — that's the crime scene. The bug is the criminal. You gather clues (add print statements), examine evidence (check edge cases), follow logical deduction (trace through your code), and eventually catch the culprit! Every great programmer is a great detective.

What is it?

Debugging is the art of finding and fixing errors in your code. It's arguably the most important practical skill in competitive programming. This lesson covers the most common bugs (off-by-one, overflow, uninitialized variables), systematic debugging techniques (print statements, edge case testing), and good habits that prevent bugs in the first place.

Real-world relevance

The term 'bug' in computing dates back to 1947 when a moth got stuck in the Harvard Mark II computer. Grace Hopper's team literally found a bug! Today, companies like Google and NASA spend enormous resources on testing and debugging. The Ariane 5 rocket exploded in 1996 because of an integer overflow — a bug that cost $370 million!

Key points

Code example

#include <bits/stdc++.h>
using namespace std;

int main() {
    // EXAMPLE: Find the maximum subarray sum (common CP problem)
    // Let's debug it step by step!
    
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];
    
    // Kadane's algorithm (simplified)
    long long maxSum = a[0];       // NOT 0! (what if all negative?)
    long long currentSum = a[0];   // Start with first element
    
    cerr << "Starting: maxSum=" << maxSum << " currentSum=" << currentSum << "\n";
    
    for (int i = 1; i < n; i++) {  // Start from 1, not 0!
        currentSum = max((long long)a[i], currentSum + a[i]);
        maxSum = max(maxSum, currentSum);
        
        // Debug print — comment out before submitting!
        cerr << "i=" << i << " a[i]=" << a[i] 
             << " currentSum=" << currentSum 
             << " maxSum=" << maxSum << "\n";
    }
    
    cout << maxSum << "\n";
    
    // === DEBUGGING CHECKLIST ===
    // 1. Did I read all input correctly?
    // 2. Are my loop bounds right (no off-by-one)?
    // 3. Did I initialize all variables?
    // 4. Can any calculation overflow int?
    // 5. Did I handle edge cases (n=1, all negative)?
    // 6. Does my output match the required format?
    // 7. Did I test with ALL given examples?
    
    return 0;
}

Line-by-line walkthrough

  1. 1. vector a(n); — we use a vector instead of int a[n] to avoid variable-length array issues on some compilers.
  2. 2. long long maxSum = a[0]; — we initialize to the first element, NOT 0! If all numbers are negative (like -3, -1, -5), the answer is -1, not 0. Initializing to 0 would be a bug.
  3. 3. long long currentSum = a[0]; — same here. We also use long long to prevent integer overflow when numbers are large.
  4. 4. for (int i = 1; i < n; i++) — we start from index 1, not 0, because we already used a[0] for initialization. Starting from 0 would process a[0] twice.
  5. 5. currentSum = max((long long)a[i], currentSum + a[i]); — at each step, we choose: start fresh from a[i], or extend the current subarray. This is Kadane's algorithm!
  6. 6. cerr << ... — debug output goes to cerr (standard error), which is separate from cout (standard output). The judge only looks at cout, so cerr won't cause Wrong Answer. Remove or comment out before submitting for cleaner code.
  7. 7. The debugging checklist at the bottom covers the most common sources of bugs. Going through this checklist before submitting can save you many Wrong Answer penalties!

Spot the bug

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    int a[n];
    for (int i = 0; i < n; i++) cin >> a[i];
    
    long long sum;
    for (int i = 0; i < n; i++) {
        sum += a[i];
    }
    cout << sum << "\n";
    return 0;
}
Need a hint?
Look at the line 'long long sum;' — what value does sum start with if you don't initialize it?
Show answer
The bug is an uninitialized variable! 'long long sum;' without '= 0' means sum starts with whatever random garbage value was in memory. It could be 0 (making the program appear to work) or it could be 7293847192 (giving a completely wrong answer). This is especially tricky because it might work on YOUR computer but fail on the judge's computer. The fix is simple: 'long long sum = 0;' ALWAYS initialize your variables!

Explain like I'm 5

Imagine you're building a LEGO castle and something looks wrong. Maybe a wall is crooked or a piece is missing. You don't throw the whole thing away! You look carefully at each section, compare it to the picture, and find the one piece that's in the wrong spot. Then you fix just that one piece. Debugging code is exactly the same — look carefully, find the mistake, fix it. You're a code detective!

Fun fact

Microsoft once estimated that debugging takes 50% of all programming time. The average programmer creates about 15-50 bugs per 1000 lines of code! In competitive programming, the #1 cause of Wrong Answers isn't wrong algorithms — it's implementation bugs. Getting good at debugging can improve your rating more than learning new algorithms!

Hands-on challenge

Here's a buggy program that's supposed to find the second largest number in an array. Find and fix ALL the bugs: int n; cin >> n; int a[n]; for(int i=0; i> a[i]; int max1=0, max2=0; for(int i=0; imax1) { max2=max1; max1=a[i]; } } cout << max2; Hint: there are at least 3 bugs. Consider: loop bounds, initialization, and what happens when the second largest isn't found correctly.

More resources

Open interactive version (quiz + challenge) ← Back to course: CP Zero to Hero