#include <stdio.h>
int main() {
int x, y, a[500], b, c = 0, d, e;
for (x = 100, y = 188 - x, b = 0; x <= 188; x++, b++) {
a[b] = (170 - y) * (550 / (x - 100)); // 💣 危險!
if (c < a[b]) {
c = a[b]; d = x; e = y;
}
}
printf("攻擊為 %d\n防御為 %d\n傷害為 %d", x, y, c);
return 0;
}
程式編譯通過,執行卻拋出「記憶體錯誤」或直接崩潰。罪魁禍首在於第 6 行:
a[b] = (170 - y) * (550 / (x - 100));
當 x = 100 時,分母 (x - 100) = 0,觸發 整數除零 (Division by Zero),導致未定義行為 (UB),典型表現為程式崩潰或拋出 SIGFPE 信號。
x = 100 改為 x = 101,避開除零點。if (x != 100) {
a[b] = (170 - y) * (550 / (x - 100));
} else {
a[b] = 0; // 或其他預設值
}
double 並最後四捨五入。| 工具/技巧 | 用法 | 適用場景 |
|---|---|---|
| AddressSanitizer (ASan) | gcc -fsanitize=address -g test.c | 緩衝區溢位、Use-after-free、雙重釋放、堆疊溢位 |
| Valgrind Memcheck | valgrind --leak-check=full ./test | 記憶體洩漏、非法讀寫、未初始化變數 |
| GDB 斷點除錯 | gdb ./test → break 6 → run → print x | 逐步追蹤變數值、呼叫堆疊、條件斷點 |
| Visual Studio 除錯器 | F9 設斷點 → F5 啟動 → 監看視窗輸入 x-100 | Windows 原生開發、混合模式除錯、記憶體視窗 |
| 編譯器警告 | gcc -Wall -Wextra -Wpedantic -Werror | 編譯期捕捉除零風險、隱式轉換、未使用變數 |
INT_MAX + 1、INT_MIN - 1。int *p = NULL; *p = 1;。int a[10]; a[10] = 0;。int x; printf("%d", x);。free(p); *p = 1;。free(p); free(p);。1 << 32 (在 32 位元 int 上)。核心心法
1. 開啟最高警告等級 並視警告為錯誤 (-Werror)。
2. 善用 Sanitizer:-fsanitize=address,undefined能在執行期精準定位 UB。
3. 防禦性程式設計:除法前檢查分母、指標解引用前檢查非空、陣列存取前檢查索引範圍。
4. 單元測試覆蓋邊界值:0、-1、MAX、MIN、NULL、空字串。