<assert.h> 提供運行期斷言機制:檢查條件,失敗時輸出診斷信息並終止程序。僅用於調試,發布版通過宏禁用。
#include <assert.h>
void func(int *ptr) {
assert(ptr != NULL); // 條件為假(0)時觸發
*ptr = 42;
}
stderr 輸出:Assertion failed: expression, file filename, line line_numberabort() 異常終止程序 (生成 core dump)NDEBUG (#define NDEBUG 或編譯旗標 -DNDEBUG) → assert 展開為空操作 ((void)0)assert 正常檢查
// debug.c
#include <assert.h>
#include <stdio.h>
int divide(int a, int b) {
assert(b != 0); // 除零檢查
return a / b;
}
int main() {
printf("%d\n", divide(10, 2));
printf("%d\n", divide(10, 0)); // 觸發斷言
return 0;
}
# 調試版編譯 (啟用斷言)
gcc -g -O0 -o debug debug.c
./debug
# 輸出:
# 5
# Assertion failed: b != 0, file debug.c, line 6
# Aborted (core dumped)
# 發布版編譯 (禁用斷言)
gcc -O2 -DNDEBUG -o release debug.c
./release
# 輸出:
# 5
# Floating point exception (core dumped) -- 實際除零硬件異常
// 正確:檢查內部不變量
void push(Stack *s, int val) {
assert(s != NULL);
assert(s->size < s->capacity); // 邏輯保證不會滿
s->data[s->size++] = val;
}
// 錯誤:檢查外部輸入/運行期錯誤
int read_config(const char *file) {
FILE *fp = fopen(file, "r");
assert(fp != NULL); // 文件不存在是正常運行期錯誤,應返回錯誤碼
// ...
}
// 危險:釋放版條件不執行,導致邏輯缺失
assert(ptr = malloc(100)); // 發布版不分配內存!
assert((fp = fopen("x")) != NULL); // 發布版不打開文件!
// 正確:副作用分離
void *ptr = malloc(100);
assert(ptr != NULL);
FILE *fp = fopen("x");
assert(fp != NULL);
#include <assert.h> // C11 _Static_assert 在 assert.h 中
_Static_assert(sizeof(int) >= 4, "int 至少 32 位");
_Static_assert(CHAR_BIT == 8, "平台字節非 8 位");
_Static_assert(FLT_RADIX == 2, "浮點非二進制");
#ifndef NDEBUG
#define MY_ASSERT(cond, fmt, ...) \
do { \
if (!(cond)) { \
fprintf(stderr, "ASSERT: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
abort(); \
} \
} while(0)
#else
#define MY_ASSERT(cond, fmt, ...) ((void)0)
#endif
// 使用
MY_ASSERT(index < count, "索引越界: index=%d, count=%d", index, count);
| 誤區 | 後果 | 正確做法 |
|---|---|---|
| 用於輸入驗證 | 發布版跳過檢查,安全漏洞 | 用 if 返回錯誤碼/拋異常 |
| 條件有副作用 | 發布版邏輯缺失 | 副作用分離 |
| 生產代碼依賴 assert 終止 | 發布版行為改變 | 關鍵錯誤用顯式錯誤處理 |
| assert 在釋放版為空導致變量未用警告 | 編譯警告 | (void)expr 或編譯器屬性 |
[[assert: cond]]、[[pre: cond]]、[[post: cond]]-fsanitize=address,undefined 運行期檢測越界、UBASSERT_*/EXPECT_*、Unity TEST_ASSERT