Script Valley
Debugging: A Systematic Approach
Reading Code to Find BugsLesson 2.1

How to trace program execution mentally step by step

mental execution model, variable state tracking, execution order, tracing loops, side effects

Mental Execution

The fastest way to find a bug without a debugger is to become the computer. Read each line in execution order, maintaining a table of variable values in your head or on paper. When a variable holds a value you did not expect, you found the propagation point.

How to Trace

Create a simple table: columns are variable names, rows are execution steps. Update each cell as you encounter an assignment. Track conditional branches -- write the condition and its evaluated result. When you hit a loop, trace the first two iterations and the last one.

function sumPositive(nums) {
  let total = 0;         // total = 0
  for (let i = 0; i <= nums.length; i++) {  // bug: <= instead of <
    if (nums[i] > 0) {
      total += nums[i];  // i=3: nums[3] is undefined, silent failure
    }
  }
  return total;
}
// Trace: i=0,1,2,3. At i=3 nums[3]=undefined, condition false.
// Bug found: off-by-one in loop bound

Side Effects Are Hidden State

Functions that modify external state -- globals, database rows, files -- make tracing harder because the effect is not visible in the local scope. Mark every function call that has side effects as you trace. If you cannot tell whether a function has side effects, assume it does and check its definition before continuing.

Up next

How boundary conditions cause most logic bugs

Sign in to track progress

How to trace program execution mentally step by step โ€” Reading Code to Find Bugs โ€” Debugging: A Systematic Approach โ€” Script Valley โ€” Script Valley