Debugging by Tracing Execution
Code file order (top to bottom) is not the same as execution order (the actual sequence the program runs).
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?
1. 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.
2. 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.
3. 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.
4. 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.
5. 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
Treating file order as execution order
The order in the file is not necessarily the actual sequence the program runs.
Fix:
At each point, identify the next operation reached by execution.Tracing every conditional branch as if it runs
A conditional selects a path, so the actual execution trace follows the selected branch.
Fix:
Determine which branch is taken and continue from that branch.Treating a loop as one ordinary step
A loop can make part of the execution path repeat.
Fix:
Record the loop activity as repeated execution before moving to the next point.Ignoring function calls
A function call changes where execution proceeds.
Fix:
Move 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.