C++ V2 · TOOLCHAIN · 54
Compile / Link / Runtime Debug:不要把所有「跑不起來」都叫程式錯
C++ source 不會直接變 process。Build pipeline 中每層都有不同輸入、輸出與 failure evidence。真正高效的 debug 是先找到「最早沒有成功的層」,而不是看到紅字就改 pointer、include 或邏輯。
Learning outcomes
- 能畫 source → object → executable → process。
- 區分 preprocess/compile/link/runtime/logic failure。
- 能從 diagnostic 判斷問題層級。
- 理解 header declaration 與 source definition 的基本角色。
- 能使用 warnings、debugger/sanitizer、regression cases 建立 evidence chain。
1. Why now:Compile 成功只是 Pipeline 中的一個 Gate
main.cpp
↓ compile
main.o
↓ link
grade-analyzer
↓ OS launch
process
↓ execute
stdout/stderr/exit code
同樣一句「程式壞了」,可能發生在完全不同的 layer。
2. Mental model:每一層都要先成功,下一層才存在
source valid?
↓ yes
object produced?
↓ yes
symbols resolved?
↓ yes
executable produced?
↓ yes
process launched?
↓ yes
behavior correct?
這條 evidence chain 能避免在 executable 根本沒產生時去查 runtime crash。
3. Worked Example A:Compile Error
int main() {
int score = ;
}
Compiler 無法把 source 轉成有效 object code。第一個 evidence 通常是 file/line/diagnostic。
4. Preprocessor / Include Failure
#include "grade_book.hpp"
如果 header path 不存在或 include configuration 錯,failure 可能在 preprocessing/compile 前段。不要把它誤認成 linker 問題。
5. Worked Example B:Declaration 有了,但 Definition 沒進 Link
// grade.hpp
int gradeOf(int score);
// main.cpp
#include "grade.hpp"
int main() {
return gradeOf(90);
}
如果沒有提供對應 definition,或 implementation object file 沒加入 link inputs,可能出現 undefined reference / unresolved external symbol。
6. Build Trace:Two Translation Units
g++ -std=c++20
-c main.cpp
-o main.o
g++ -std=c++20
-c grade.cpp
-o grade.o
g++ main.o grade.o
-o grade-analyzer
前兩步各自 compile;最後一步 linker 把 symbols 組成 executable。
7. Worked Example C:Runtime Undefined Behavior
int* ptr = nullptr;
std::cout << *ptr;
Source 可能成功 compile/link,但 process 執行到 invalid dereference 時進入 undefined behavior。這是 runtime memory layer。
8. Logic Error:所有技術層都成功,答案仍錯
int total = 7;
int count = 2;
double average =
total / count;
// 3.0, expected 3.5
Executable 可正常退出 0,不代表 business contract 正確。Regression tests 才能抓這層。
9. Warnings:不是全部都能忽略的「建議」
g++ -std=c++20
-Wall
-Wextra
-pedantic
main.cpp
-o grade-analyzer
Warnings 不保證一定是 bug,但它們是高價值 evidence。初學階段應盡量做到「理解每個 warning」,而不是關掉。
10. Sanitizer:把一部分 Runtime Memory Evidence 變明顯
g++ -std=c++20
-Wall
-Wextra
-fsanitize=address,undefined
-g
main.cpp
-o grade-analyzer
AddressSanitizer/UBSan 能幫你把某些 memory/undefined behavior 問題轉成更具體 diagnostics,但不是形式證明,也不會抓到所有 bug。
11. Debugger / Stack Trace:看 Process 正在哪裡失敗
main()
↓
run()
↓
average()
↓
invalid access
Runtime crash 時要看 call stack、local variables、faulting instruction/function,而不是只看最後輸出。
12. Common mistakes
A. Undefined reference 時去改 pointer
這通常是 link/symbol 問題。
B. Compile error 時一直重跑 executable
新的 executable 根本沒產生。
C. Warning 全部忽略
可能放掉 narrowing、unused、lifetime 等重要訊號。
D. Crash 就認為「一定是 null pointer」
out-of-bounds、use-after-free、stack overflow 等也可能。
E. Exit 0 就認為功能正確
logic error 完全可能 exit 0。
13. Debug evidence:固定六步 Failure Classification
1. Did compile succeed?
2. Did link succeed?
3. Was executable updated?
4. Did process launch?
5. Did process terminate abnormally?
6. Is output/behavior correct?
每一步都要用 observable evidence 回答,而不是憑印象。
14. Guided exercise:製造四種 Failure
在最小 Grade Analyzer 裡刻意製造:
compile error
link error
runtime invalid access
logic boundary error
對每種記錄:symptom、第一個 evidence、失敗 layer、修復方式。
15. Independent exercise:Split Files
把:
isPassed()
gradeOf()
移到 grade.hpp / grade.cpp,main.cpp 只呼叫。先正確 build,再故意漏掉 grade.o link input,觀察 link diagnostic。
16. Challenge:Stale Executable
修改 source 後故意讓 compile 失敗,再執行舊 executable。說明為什麼你可能看到「程式還能跑」,但其實跑的是 stale binary;建立避免誤判的方法。
Project checkpoint:CLI Grade Analyzer · Build Evidence v4
src/
├─ main.cpp
├─ grade.hpp
└─ grade.cpp
build evidence:
compile warnings clean
link success
executable timestamp/commit known
boundary regressions pass
完成這一課後,C++ 前半段不再只是會寫 syntax,而是能說明 code 如何真正成為 process。
17. Vocabulary / Summary
- translation unit:經 preprocessing 後交給 compiler 的單位。
- object file:尚未完成最終 symbol resolution 的編譯輸出。
- linker:解析跨單位 symbols 並產生 executable。
- runtime failure:process 執行期間才發生的 failure。
- undefined behavior:標準不要求固定結果的行為。
- sanitizer:協助偵測特定 runtime errors 的 instrumentation。
18. Further reading
Knowledge check · Mastery
- 畫 source → object → executable → process。
- 看到 undefined reference 時指出第一個 failure layer。
- 完成四類 fault injection 與 split-file build。
- 完成頁面下方 C++ build/debug diagnostic practice。