C 語言無異常機制,錯誤處理依賴返回值約定 + 全局錯誤碼 errno。正確使用這三大工具,能構建健壯的錯誤診斷體系。
#include <errno.h>
extern int errno; // 實際為線程局部變量 (C11 _Thread_local)
errno.h 中 E* 宏(如 EDOM=33、ERANGE=34、ENOENT=2)。errno = 0;
double x = sqrt(-1.0); // 域錯誤
if (errno != 0) { // errno == EDOM (33)
// 處理錯誤
}
#include <string.h>
char *strerror(int errnum); // 返回靜態緩衝區指針,非線程安全
// C11 線程安全版
char *strerror_s(char *buf, size_t buflen, int errnum);
#include <stdio.h>
void perror(const char *s);
輸出格式:s: error_string\n(若 s == NULL 或 "" 則只打印錯誤串)。
perror("sqrt failed");
// 輸出:sqrt failed: Numerical argument out of domain
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
void die(const char *msg) {
if (errno) {
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
} else {
fprintf(stderr, "%s\n", msg);
}
exit(EXIT_FAILURE);
}
int main(void) {
FILE *fp = fopen("nonexist.txt", "r");
if (!fp) die("fopen failed"); // errno = ENOENT
errno = 0;
double y = strtod("xyz", NULL);
if (errno == ERANGE) die("strtod overflow");
return 0;
}
| 宏 | 值 | 含義 | 典型場景 |
|---|---|---|---|
EPERM | 1 | 操作不允許 | 無權限調用系統調用 |
ENOENT | 2 | 文件/目錄不存在 | fopen、open、stat |
EINTR | 4 | 被信號中斷 | read/wait 需重試 |
EIO | 5 | I/O 錯誤 | 硬件故障 |
ENOMEM | 12 | 內存不足 | malloc、mmap |
EACCES | 13 | 權限被拒絕 | 文件訪問權限不足 |
EINVAL | 22 | 無效參數 | API 參數錯誤 |
ERANGE | 34 | 結果超出範圍 | 數學函數、轉換函數 |