[2026] Static Analysis in C++: Enforce Quality with Clang-Tidy & Cppcheck [#41-1]
이 글의 핵심
Integrate clang-tidy (.clang-tidy, compile_commands) and Cppcheck into editors and CI. Fix use-after-move, leaks, and style drift before runtime. SEO: clang-tidy, cppcheck, static analysis, CI.
Introduction: catch bugs before you run
Static analysis inspects source without executing it. Clang-Tidy provides hundreds of checks for modern C++, performance, and bugprone patterns. Cppcheck is compiler-independent and strong on memory, null derefs, and bounds issues. Together they complement each other.
Covers: scenarios, .clang-tidy, compile_commands.json, representative checks, --fix, Cppcheck flags/suppressions, CI workflows, incremental analysis, adoption strategy.
Table of contents
- Why static analysis
- Clang-Tidy
- Cppcheck
- Complete demo project
- Common errors
- CI integration
- Production patterns
- Summary
1. Why static analysis
Production crashes from null derefs, use-after-move, range-for copies, magic numbers—many are detectable statically when configured. Real-world impact: a single use-after-move bug in production can crash servers under load, but clang-tidy catches it at commit time with bugprone-use-after-move.
Common scenarios:
- Null pointer dereference: Cppcheck flags
*ptrwithout null checks - Use-after-move: Clang-tidy detects accessing moved-from objects
- Performance:
performance-for-range-copyfinds expensive copies in range loops - Style drift:
readability-identifier-namingenforces team conventions 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 실행 예제
flowchart LR
A[Compile] --> B[Clang-Tidy]
A --> C[Cppcheck]
B --> D[Gate merge]
C --> D
Team benefit: catching issues before code review saves 10-30 minutes per PR and reduces back-and-forth.
2. Clang-Tidy
Clang-Tidy is LLVM’s linter with 400+ checks. It requires compile_commands.json to understand your build flags and includes.
Setup: create .clang-tidy in your project root:
아래 코드는 yaml를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 실행 예제
Checks: 'bugprone-*,modernize-use-nullptr,performance-for-range-copy,readability-identifier-naming'
WarningsAsErrors: '
HeaderFilterRegex: '.*'
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: CamelCase
Generate compile_commands.json with CMake:
cmake -B build -S . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
clang-tidy -p build src/*.cpp
Auto-fix: --fix applies safe fixes, but always review with git diff and run tests. Example: modernize-use-nullptr converts NULL to nullptr automatically.
Editor integration: VS Code C++ extension and CLion read .clang-tidy automatically, showing warnings inline as you type.
3. Cppcheck
Cppcheck is compiler-independent and excels at detecting memory leaks, null derefs, and out-of-bounds access. Unlike clang-tidy, it doesn’t need compile_commands.json.
Basic usage:
cppcheck --enable=all --suppress=missingIncludeSystem -I include --error-exitcode=1 -j8 src/
Flags explained:
--enable=all: all checks (warning, style, performance, portability)--suppress=missingIncludeSystem: ignore system headers-I include: add include paths--error-exitcode=1: fail CI on errors-j8: parallel analysis (8 threads) Suppression: add// cppcheck-suppress nullPointerabove false positives, or use--suppressions-list=suppressions.txtfor project-wide rules. Complementary: Cppcheck finds issues clang-tidy misses (e.g.,if (x = 5)assignment in condition) and vice versa. Run both for comprehensive coverage.
4. Demo project
Check in CMakeLists.txt, a sample .clang-tidy, and run-static-analysis.sh alongside your project for reproducible CI runs.
5. Common errors
- Missing
compile_commands.json→ configure CMake with export. - Too many diagnostics on legacy code → enable gradually, NOLINT sparingly, exclude
third_partyviaHeaderFilterRegex.
6. CI integration
GitHub Actions example: 다음은 yaml를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
name: Static Analysis
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install tools
run: sudo apt-get install -y clang-tidy cppcheck
- name: CMake
run: cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: Clang-Tidy
run: clang-tidy -p build src/*.cpp
- name: Cppcheck
run: cppcheck --enable=all --error-exitcode=1 src/
Optimization: for large repos, run only on changed files using git diff --name-only origin/main...HEAD | grep '\.cpp$' to filter files. This reduces CI time from minutes to seconds.
Fail-fast: set --warnings-as-errors in clang-tidy or --error-exitcode=1 in cppcheck to block merges with issues.
7. Production patterns
Pre-commit hooks, clangd in-editor, split warnings-as-errors by check category.
8. Summary
| Tool | Focus |
|---|---|
| Clang-Tidy | Modern C++, performance, many autofixes |
| Cppcheck | Memory, control flow without full compilation |
| Next: ASan/TSan (#41-2) | |
| Previous: Docker for C++ (#40-3) |
Keywords
clang-tidy, cppcheck, static analysis, compile_commands.json, CI quality