Debugging by Tracing Execution
Code file order (top to bottom) is not the same as execution order (the actual sequence the program runs).
Try it: Debug by Tracing Execution
How to debug a program that runs but gives the wrong answer: compare expected and actual output, trace the lines in the order they really run with a variable watch table (or an inserted debug print), find the first line where a value goes wrong, then choose a fix and re-run to check it.
How it works
- State the expected output from the specification, run the program and compare: a difference is the evidence you debug from.
- Trace in execution order, not file order: loops repeat lines, if/elif picks one branch, and the watch table records every variable before each line runs.
- An inserted print('debug: ...', value) shows the same state in the output; it must not change what the program itself prints.
- Look for the first place a value differs from what it should be (an off-by-one range, > instead of >=, a total reset inside the loop, two names for one list, a str from input()). Where the wrong value shows up is only the symptom.
- Change one thing with a reason, re-run, and compare again: a fix that makes an error disappear can still leave the output wrong.
Default run (14 steps): Sum 1..n: Add up the whole numbers from 1 to n (n included) and print the sum. Press Play to trace it line by line. … Finished, but the output is wrong: got sum of 1 to 5 is 10, expected sum of 1 to 5 is 15.
Simplified: The lab's own small Python interpreter runs fixed, hand-written programs (you pick the program, the fix and a value; your text is never executed). Every program the lab can show was run in CPython 3.12 and the lab reproduces its output, its traceback text and its line-by-line trace. Six short programs, one editable value each; input() receives the value you type in the lab. Lines starting with "debug:" are ignored when comparing the output with the expected output.
Loading the simulation…
The Two Orders
When debugging, it is tempting to read a program exactly as it appears in the file: first line, second line, third line, and so on. That reading order is the code file order. It is not necessarily the order in which the program runs. Execution order is the actual sequence the program follows while it runs.
Control-Flow Clues
Execution flow is the path a program actually takes. To follow that path, trace the program's function calls, conditionals, and loops. A function call can move execution into another part of the program. A conditional determines which path is taken. A loop can cause a part of the program to be followed repeatedly. These structures make the actual path different from a simple top-to-bottom reading.
- At a function call, identify the function that execution enters.
- At a conditional, identify which branch is selected.
- At a loop, identify whether the loop continues and which part is repeated.
- After each step, record what the program does next rather than returning automatically to the next visible line.
A Trace in Practice
Consider a generated program structure with a starting operation, a function call, a conditional inside that function, and a loop on the selected path. The point of the example is not to read the structure as a list. Instead, follow the route that execution takes.
Tracing the Actual Route
A program starts, calls a function, evaluates a conditional inside that function, and then follows a loop when the selected branch reaches it. How should the execution be traced?
- 11. Start at the program entry
Begin with the operation where execution starts. Do not assume that every item appearing above it in the file has just run.
- 22. Enter the called function
When the starting operation makes a function call, move to the function body. The next execution step is inside that function.
- 33. Resolve the conditional
At the conditional, determine which branch is selected. Trace only the path the program takes rather than treating every branch as executed.
- 44. Follow the loop
If the selected path reaches a loop, follow the loop's repeated path as part of the execution sequence. Record each relevant pass before moving onward.
- 55. Continue from the resulting point
After the function call, conditional, and loop have been traced, continue following the next operation in the route.
The trace is the actual path: program start, function call, selected conditional branch, loop activity, and the next operation. This path is the execution order, even if those elements are separated or arranged differently in the file.
Tracing Mistakes
Common mistake Treating file order as execution order
What it looks likeReading every item from the top of the file downward without following calls, branches, or repetition.
Why it failsThe order in the file is not necessarily the actual sequence the program runs.
Do this insteadAt each point, identify the next operation reached by execution.
Common mistake Tracing every conditional branch as if it runs
What it looks likeIncluding both possible paths in one execution trace.
Why it failsA conditional selects a path, so the actual execution trace follows the selected branch.
Do this insteadDetermine which branch is taken and continue from that branch.
Common mistake Treating a loop as one ordinary step
What it looks likeWriting the loop once in the trace and immediately moving on.
Why it failsA loop can make part of the execution path repeat.
Do this insteadRecord the loop activity as repeated execution before moving to the next point.
Common mistake Ignoring function calls
What it looks likeContinuing with the next visible item in the file instead of entering the called function.
Why it failsA function call changes where execution proceeds.
Do this insteadMove into the called function, trace its path, and then continue from the resulting point.
Write a short execution trace while debugging. Each entry should describe the next function call, selected conditional path, or loop activity. This keeps attention on what the program actually does rather than on the visual arrangement of the file.
Trace Before Guessing
Create an execution trace for this generated structure: the program starts, reaches a conditional, selects a branch that makes a function call, and then encounters a loop. List the execution events in the order they occur. Then explain why that order may differ from the order in which the structures appear in the file.
Hints
- Begin at the program's starting point.
- At the conditional, follow only the selected branch.
- When the function call occurs, trace inside the function before continuing.
- Include the loop's repeated activity in the execution sequence.
Why the Trace Helps
Debugging by tracing execution is a way to read a program according to its behavior. Instead of assuming that top-to-bottom file order explains everything, follow function calls, conditional choices, and loop repetition. This often provides a more sensible and effective way to understand what the program actually does, which supports both debugging and predicting program behavior.
Key Takeaways
- Code file order and execution order are not necessarily the same.
- Execution-flow reading follows the path the program actually takes.
- Function calls, conditionals, and loops are key points to trace.
- A useful trace records the next operation, selected branch, and repeated activity.
- Understanding execution flow helps with debugging and predicting program behavior.