← Daily LogFIELD LOG No. 037 — 15 Jul 2026
The linked list drill that found two new bugs
A pre-Milestone warm-up on linked lists — walking the list, delete_node — turned into six rounds of debugging and two new formalized mistake patterns, one of them caught only by AddressSanitizer.
What I got through
- Traced deleting a middle node — the mechanism (prev/current tracking, relinking) was right and unaided, but I didn't actually spell out the
free()step or the concrete final list state until I forced myself to re-trace it explicitly. - Traced deleting the head node — correctly spotted that
prev == NULLsignals the special case, since the loop never runs at all. But I described the update as "increment head" instead of the real*head = current->nextreassignment, and mixed up the function'sstruct node **headparameter with the caller's ownstruct node *headvariable. Took two hand-drawn diagrams to untangle. - Worked through what a single-pointer version would do to the caller's
headon my own — got it right unaided, which was the real evidence the double-pointer mechanism had actually landed, imprecise trace wording aside. - Wrote
delete_nodeitself — six rounds. Round one was a plain compile error. Round two compiled clean but hid a real bug: two independentifblocks let a second block re-touch a node the first one had already freed — a confirmed heap-use-after-free that still printed the correct list on a plain run, only caught because I ran it under AddressSanitizer for the first time this curriculum. Rounds three and four repeated the same stray-token typo. Round five restructured toelse if, which fixed that bug but exposed a new one —prev == NULLalone doesn't tell a head-match apart from an empty list. Round six combined both conditions and passed all five cases (head, middle, tail, not-found, empty) clean.
Mistakes I made
- Wrote two separate top-level
ifs where I meant "exactly one of these should run" — nothing about that shape actually enforces exclusivity, so the second block ran anyway on freed memory. - Treated
prev == NULLas sufficient proof of a head-match, when it's only necessary — an empty list produces the identical state.
What's next
This closes out the linked list portion of the pre-Milestone drill queue. Still pending before the actual Milestone Test: a leftover post/pre-increment trace question, a precision pass on a couple of older nuance errors, and two light confirmation passes.
Field note
AddressSanitizer got its first real use in this curriculum this session. Plain gcc -Wall and eyeballing the output would have missed the use-after-free entirely — it only looked wrong once something actually inspected the memory.
Notes from readers
Comments — via GitHub