32. Static analysis: clang-tidy, cppcheck, the Clang Static Analyzer
# Catches style + some real bugs (uninitialized use, modernize suggestions)
clang-tidy app.c -- -std=c17
# Path-sensitive analysis: finds null derefs, leaks, dead stores by
# actually simulating execution paths through your code
scan-build clang -std=c17 -c app.c
# A fast, dependency-free linter — great as a pre-commit hook
cppcheck --enable=all --std=c17 app.c
Real-world example. scan-build (the Clang Static Analyzer's driver)
is what will flag Section 10.2's memory leak without running the
program at all — it walks every path through leak(), sees that buf
is assigned from malloc and never reaches a free on any path, and
reports it at the exact allocation line. Static analysis and the
dynamic tools from Section 14/31 (ASan/UBSan/fuzzing) are complementary:
static analysis finds bugs on paths your tests never execute; dynamic
tools find bugs your static analyzer can't reason about (attacker-
controlled runtime values, complex aliasing). Serious C projects run
both, plus a real test suite, in CI on every commit.