a symptom versus the root cause
If your car's warning light comes on, the light is not the problem - it is telling you about a problem somewhere else. Treating the light as the issue (covering it with tape) leaves the real fault to do more damage. Bugs work the same way. A symptom is what you observe going wrong - the crash, the segfault, the wrong output, the hang. The root cause is the actual mistake that, several steps earlier, set up the conditions for that symptom. Confusing the two is the single most common way debugging goes wrong.
Concretely, in systems programming the gap between symptom and cause is often large and the symptom is often misleading. A segmentation fault is a classic symptom: the program tried to use an address it was not allowed to, and the OS killed it - but the crash happens where the bad pointer is finally dereferenced, while the root cause is wherever that pointer was set wrong, perhaps in a different function long before. Worse, undefined behavior may corrupt memory with no crash at all, so the symptom can appear arbitrarily far from the cause, or not appear until much later when unrelated code stumbles over the damage. A crash, a wrong number, a hang - these are effects; the bug is the line that made them inevitable. The discipline is to walk backward from the symptom (read the backtrace, inspect who passed the bad value, use a watchpoint to catch the corruption) until you reach the first place reality diverged from intent - that is the root cause.
Why it matters: fixing a symptom rather than its cause is how bugs come back. Adding a null check at the crash site stops that crash but leaves the real defect - whatever produced the null - free to cause new failures elsewhere; the bug just moves. A real fix addresses the place where the program first did something wrong, after which the symptom cannot recur for that reason. The honest discipline: 'it stopped crashing' is not the same as 'I found and fixed the bug'; demand an explanation of why the original problem can no longer happen, and be suspicious of any fix you cannot explain - it has probably masked a symptom, not removed a cause.
A program segfaults in print_name() when name is NULL. Patching print_name to skip NULL stops the crash - but the real bug is that load_user() returned NULL on a missing record and the caller never checked. Fix the check in load_user(), and the symptom (and any future variants of it) cannot recur.
The crash is the symptom; the unchecked NULL from load_user() is the root cause.
A segmentation fault, a wrong result, or a hang is a symptom, not the bug - and undefined behavior can corrupt silently with the symptom appearing far away or much later, or not at all. 'It stopped crashing' after a change you cannot explain usually means you masked a symptom, not removed its cause.