C 標準 (ISO/IEC 9899) 規定:某些程式碼構造若被執行,標準不施加任何要求。編譯器可產生任意結果:正常執行、崩潰、輸出垃圾資料、甚至刪除硬碟 (理論上)。
關鍵區別:
int 位寬、位元欄位分配順序)。int a[5]; a[5] = 0; // 寫入第 6 個元素 char *p = "hello"; p[0] = 'H'; // 修改字串常值 (唯讀記憶體) int *q = malloc(4); q[1] = 2; free(q); q[0] = 1; // Use-after-free
int x = INT_MAX; x++; // UB! 無號整數溢位定義為模 2^n 環繞,有號則 UB
int *p = NULL; *p = 42; // 崩潰或靜默破壞
int x; printf("%d", x); // 值不確定,可能觸發陷阱表示
char *s = "hello"; s[0] = 'H'; // UB,s 指向唯讀段
int i = 0; i = i++; // UB: i 在同一序列點被修改兩次
int a[10]; a[i++] = i; // UB: 存取 i 且修改 i 無序列點
printf("%d %d", i++, i++); // UB: 參數求值順序未指定,且 i 重複修改
float f = 1.0f; int *p = (int*)&f; // 透過 int* 存取 float 物件 int bits = *p; // UB (C99 6.5/7),除非用 union 或 memcpy
1 << 32; // UB: 位移量 >= 型別寬度 1 << -1; // UB: 負數位移 -1 << 1; // UB: 有號負數左移
if (x+1 < x) ... 有號溢位 UB → 編譯器判定條件永假 → 整個 if 被優化掉。| 工具 | 類型 | 用法 |
|---|---|---|
| AddressSanitizer (ASan) | 動態 | gcc -fsanitize=address -g 偵測越界、UAF、雙重釋放 |
| UndefinedBehaviorSanitizer (UBSan) | 動態 | -fsanitize=undefined 偵測整數溢位、空指標、位移錯誤等 |
| MemorySanitizer (MSan) | 動態 | -fsanitize=memory 偵測未初始化讀取 |
| ThreadSanitizer (TSan) | 動態 | -fsanitize=thread 偵測資料競爭 |
| Clang Static Analyzer | 靜態 | scan-build make 路徑敏感分析 |
| Cppcheck | 靜態 | cppcheck --enable=all src/ |
| Compiler Warnings | 靜態 | -Wall -Wextra -Wpedantic -Werror |