Debugging values and traversing dynamic arrays

Computer Science II · Lab 4 ·

A debugger pauses at a loop while showing index 2 and value 9.
Inspecting the current index and element helps expose boundary and traversal errors.

A debugger helps you observe the values a running program actually uses. That is useful when a formula is mathematically sound but the output is wrong: the defect may be an input, a parameter, an initialization, or a boundary rather than the formula itself.

Review CS1: function calls and CS1: pointers and lifetime. This lab develops a method for locating the first wrong state, then applies the same method to dynamic-array traversal.

Pause where evidence can change your decision #

A breakpoint pauses execution when the program reaches a selected location. A good first breakpoint is just before the first incorrect calculation. Inspect the values about to enter that calculation, then compare them with the expected inputs.

Stepping over a function call runs it without following its body statement by statement. Stepping into enters the call so you can inspect its parameters and local work. Continuing resumes execution until another stop condition. Choose the operation according to the question: if the returned value is suspicious, step into; if only the caller's later use is suspicious, first inspect the caller before and after stepping over.

A stack trace shows the active chain of calls. It helps establish which function is currently executing and which call led there. Local variables belong to particular calls, so the same variable name in two functions does not identify shared storage.

Do not change the code simply because a value looks unfamiliar. First decide whether that value is wrong under the contract and where it first differed from the expected state. This supplies a reason for the correction.

Check a quadratic calculation in stages #

The quadratic formula is (-b ± sqrt(b² - 4ac)) / (2a) under its assumptions. A must be nonzero for a quadratic with this denominator. A negative discriminant does not produce real roots under the ordinary real square-root calculation.

Use a small hand-checkable example to make the intermediate values visible. With a equal to one, b equal to minus three, and c equal to two, the discriminant is nine minus eight, or one. Its square root is one. The numerator choices are three plus one and three minus one, and the denominator is two. The expected real roots are two and one.

At the breakpoint, first inspect a, b, and c. If those are not the intended values, investigate input or argument passing. If they are correct, inspect the discriminant. If that is correct, inspect the square-root result and denominator. This order narrows the fault instead of changing several stages at once.

A negative square-root argument, an invalid denominator, or incorrect values passed into a correct expression can each explain unexpected nonnumeric output. They are possible causes, not interchangeable diagnoses. The observed runtime state determines which cause is relevant.

Follow the argument across the call boundary #

A value parameter receives a copy. A reference parameter can refer to the caller's object. A local variable with the same spelling as a caller's variable is still a separate object unless an explicit relationship makes it shared.

If the caller has the right coefficients but the function does not, inspect the call's argument order and the selected parameter declarations. If a local value was never initialized, finding a similar name in another function does not initialize it. If the function changes a reference argument, inspect the caller's object afterward as well.

The debugger displays what the program did, including a mistake. It does not automatically decide which variable the programmer intended to use. Keep the mathematical specification and function contract beside the observed state.

Traverse a live allocation with a fixed endpoint #

A dynamic array can be accessed with indexes or pointer arithmetic. For a valid i, values[i] and *(values + i) refer to the same element. The length still comes from the actual allocation, not from the fact that a pointer can be advanced syntactically.

Suppose three active integers are two, four, six. A traversal begins at the base, reads two, advances one element, reads four, advances again, and reads six. The next position is one past the active range and is a stopping marker for this traversal. If capacity exceeds the active count, that position may still be within allocated storage, but it is not an accepted active observation. The separate one-past-allocation pointer is never a readable element.

Advancing a pointer changes its stored position. Assigning through the dereferenced pointer changes the current element. Those are separate operations, just as changing a loop index differs from changing an array value. Watch both the address or relative position and the target value while stepping.

Keep the owning address for cleanup #

Retain the original address returned by array allocation. Use another pointer for traversal if that makes the ownership clearer. An interior pointer may reach a valid element, but it is not the address to pass to delete[]. The one-past-end position must not be dereferenced.

Pair new[] with delete[] exactly once, using the original base address. After release, all aliases into that allocation become invalid even if their stored addresses remain visible in the debugger.[1]

Practice and verification #

If the discriminant is wrong but the supplied coefficients are already wrong, where should the investigation move? Earlier, toward input and the call. A later formula edit cannot repair incorrectly supplied data.

After a correction, rerun the original failing example and a contrasting case with a known answer. For traversal, test one element and the final valid element, then confirm that no read occurs at the stopping position. Explain why the change fixes the first incorrect state; one plausible output alone does not establish that reason.

References

  1. ↑ C++ working draft: delete expressions .