$ clang -g -O0 03_divzero.c -o bin/03_divzero
$ ./bin/03_divzero ; echo "exit=$?"
computing 100 / 0 ...
Floating point exception (core dumped)
exit=136$ clang -g -O0 03_divzero.c -o bin/03_divzero
$ ./bin/03_divzero ; echo "exit=$?"
computing 100 / 0 ...
Floating point exception (core dumped)
exit=136$ gdb -q -batch -ex 'set debuginfod enabled off' \
-ex run -ex bt -ex 'print b' -ex 'info locals' \
-ex 'x/i $pc' ./bin/03_divzero
Program received signal SIGFPE, Arithmetic exception.
0x00000000004004b1 in main (argc=1, argv=0x7fffffffd888) at 03_divzero.c:87
87 int q = a / b; // <-- THE BUG
#0 0x00000000004004b1 in main (argc=1, argv=0x7fffffffd888) at 03_divzero.c:87
$1 = 0
a = 100
b = 0
q = 0
=> 0x4004b1 <main+65>: idivl -0x18(%rbp)
How to read each command:
run -> stops on SIGFPE, right at the faulting instruction.
bt -> the call stack; names main and 03_divzero.c:87.
print b -> b == 0: the divisor is the problem.
info locals -> a=100, b=0, confirming the operands.
x/i $pc -> disassemble the faulting instruction: it is an `idiv`
(signed integer divide). Proof it's an INTEGER, not FP,
fault despite the "Floating point exception" wording.$ valgrind -q ./bin/03_divzero
==57274== Process terminating with default action of signal 8 (SIGFPE): dumping core
==57274== Integer divide by zero at address 0x1002D8A124
==57274== at 0x4004B1: main (03_divzero.c:87)
valgrind/memcheck tracks MEMORY errors. A divide-by-zero is an arithmetic
fault, not a bad memory access, so memcheck adds nothing — it just lets
the SIGFPE through. Reach for a sanitizer instead:$ clang -g -O0 -fsanitize=undefined 03_divzero.c -o bin/03_divzero.ubsan
$ ./bin/03_divzero.ubsan ; echo "exit=$?"
03_divzero.c:87:15: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior 03_divzero.c:87:15
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==57286==ERROR: UndefinedBehaviorSanitizer: FPE on unknown address 0x00000042dfae
#0 0x42dfae in main debug_lab/03_divzero.c:87:15
exit=1
UBSan instruments the divide and prints the exact file:line:column and a
plain-English "division by zero" BEFORE the hardware fault. This is the
right tool for arithmetic UB.ROOT CAUSE vs CRASH SITE: The crash site is the divide. The root cause is that `b` was allowed to become 0 (here: program run with no extra args -> argc-1 == 0). In real code, validate denominators at their SOURCE, not at the divide.
arithmetic fault (SIGFPE) / UB
1 ------------------------------------------------------------
`a / b` is evaluated with b == 0. Integer division by zero is Undefined Behavior in C; on x86-64 the DIV/IDIV instruction raises a hardware exception (#DE), delivered as SIGFPE. Buggy line: `int q = a / b;`. (`b` comes from argc so the compiler can't fold it away and the divide really executes at runtime.)
"Floating point exception (core dumped)" — note the name is a misnomer: it is an INTEGER divide fault. Shell exit 136 (136 = 128 + 8 = 128 + SIGFPE). Deterministic.
Guard the divisor: if (b == 0) { fprintf(stderr, "denominator is zero\n"); return 1; } int q = a / b;
Run `./bin/03_divzero 5` (one arg => b==1). It prints q=100 and exits 0 — same code, no bug, because the input no longer drives b to 0. Bugs that depend on input are why you reproduce with the EXACT failing input. ============================================================
#include <stdio.h>
int main(int argc, char **argv) {
int a = 100;
int b = argc - 1; /* 0 when run with no extra args */
printf("computing %d / %d ...\n", a, b);
int q = a / b; /* <-- THE BUG: divide by zero */
printf("q = %d\n", q);
(void)argv;
return 0;
}A lab is done when you can say what it showed on your machine — not when you have read it.
It decides which problems come first, which drills open, which labs you see and how the Learn surface is organised. Change it any time from the switch in the top bar, or press Escape to look around first.