9.4 - Trace Tables
What trace tables are and their purpose
Trace tables provide a structured method for tracking how values change during the execution of an algorithm or piece of code. They act as a manual simulation tool, allowing programmers to step through the logic without running the program on a computer.
Key purposes of trace tables
- Detecting logic errors - These occur when code runs without syntax issues but produces incorrect results due to flawed reasoning. Trace tables highlight where the logic fails.
- Dry-running algorithms - This involves simulating the code's execution on paper, which is useful for testing subprograms or small sections of code.
- Understanding code behaviour - Trace tables can clarify what unfamiliar code does by showing step-by-step changes.
Trace tables typically use columns to represent variables or other relevant data, with each row showing the state after a specific operation.
How to construct trace tables
To build a trace table, identify the key variables in the code and create columns for each. Add rows to capture the state before and after each significant step, such as loop iterations or conditional checks.
Steps for creating a trace table:
- List the variables as column headers.
- Initialise the first row with starting values (use dashes for uninitialised items).
- For each line of code, add a new row showing updated values.
- Include additional columns if needed, such as for array lengths, outputs, or conditions.
Using trace tables to detect logic errors
Trace tables are particularly effective for dry-running code to spot logic errors. By manually executing the algorithm, you can verify if the output matches expectations and adjust the code accordingly.
Example: Tracing a function to sum odd numbers
Consider this pseudocode function that calculates the sum of all odd numbers up to a given number:
For the function call sumOfOdd(5), the trace table tracks num, count, and total:
| num | count | total |
|---|---|---|
| 5 | - | 0 |
| 5 | 1 | 1 |
| 5 | 2 | 1 |
| 5 | 3 | 4 |
| 5 | 4 | 4 |
| 5 | 5 | 9 |
- The table shows additions only for odd values of
count(1, 3, 5), resulting in a finaltotalof 9. - If the logic was incorrect (e.g., adding even numbers), the table would reveal mismatched results, indicating a logic error.
Applying trace tables to understand code functionality
Trace tables can also reverse-engineer the purpose of code by observing patterns in value changes. This is helpful when analysing existing programs or algorithms.
Example: Determining the purpose of a minimum-finding function
Examine this pseudocode function that processes an array of four elements:
For the function call test([4,6,3,1]), the trace table tracks i, arr[i], and x:
| i | arr[i] | x |
|---|---|---|
| - | - | 4 |
| 1 | 6 | 4 |
| 2 | 3 | 3 |
| 3 | 1 | 1 |
- The value of
xstarts at the first array element and only updates when a smallerarr[i]is found. - It decreases progressively to the smallest value (1), showing the function returns the minimum value in the array.
By following the changes, the table reveals the code's intent without prior knowledge.
Additional features and related debugging tools
Trace tables are flexible and can extend beyond just variables to include any relevant information for analysis.
Extended uses of trace tables
- Non-variable columns - Include details like array lengths or program outputs to provide more context.
- Custom tracking - For complex algorithms, add columns for intermediate calculations or flags that indicate state changes.
While trace tables are ideal for manual testing, larger programs often require automated tools.
Related debugging techniques
- Breakpoints - These pause program execution at specific lines, allowing inspection of variable values in real time.
- Integration with IDEs - Debugging tools in integrated development environments (IDEs) can automate tracing, complementing manual tables for thorough error checking.