首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言錯誤處理機制:errno、strerror、perror 完整使用指南

     編輯:關於C語言

C 標準庫錯誤報告三劍客:errno、strerror、perror

C 語言無異常機制,錯誤處理依賴返回值約定 + 全局錯誤碼 errno。正確使用這三大工具,能構建健壯的錯誤診斷體系。

一、errno:線程局部的錯誤碼存儲

#include <errno.h>
extern int errno;  // 實際為線程局部變量 (C11 _Thread_local)
  • 特點:只在庫函數出錯時被設置(成功不清零);值為正整數,對應 errno.h 中 E* 宏(如 EDOM=33、ERANGE=34、ENOENT=2)。
  • 正確用法:調用前手動置 0,調用後檢查非 0。
errno = 0;
double x = sqrt(-1.0);  // 域錯誤
if (errno != 0) {       // errno == EDOM (33)
    // 處理錯誤
}

二、strerror:錯誤碼轉人類可讀字符串

#include <string.h>
char *strerror(int errnum);  // 返回靜態緩衝區指針,非線程安全
// C11 線程安全版
char *strerror_s(char *buf, size_t buflen, int errnum);
  • 返回指針指向內部靜態緩衝區,後續調用會覆蓋,需立即使用或拷貝。
  • 字符串內容由實現定義,通常為英文描述(如 "Numerical argument out of domain")。

三、perror:一鍵打印到標準錯誤

#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;
}

五、常見錯誤碼速查表

六、進階最佳實踐

  1. 線程安全:C11 使用 strerror_s 或 strerrorlen_s + 自行分配緩衝區。
  2. 錯誤碼封裝:項目中定義統一錯誤碼枚舉,內部映射 errno,對外暴露領域相關錯誤類型。
  3. 資源清理:錯誤路徑必須釋放已獲取資源,推薦 goto cleanup 模式或 C++ RAII。
  4. 不濫用 errno:自定義函數返回錯誤碼或通過輸出參數傳遞,避免依賴全局狀態。
  5. 系統調用重試:遇 EINTR 必須重試(如 while ((n = read(fd, buf, sz)) < 0 && errno == EINTR);)。

掌握 errno 設置/檢查規則、strerror 線程安全陷阱、perror 快速診斷,結合統一錯誤處理框架,是編寫生產級 C 代碼的基礎功力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
宏值含義典型場景
EPERM1操作不允許無權限調用系統調用
ENOENT2文件/目錄不存在fopen、open、stat
EINTR4被信號中斷read/wait 需重試
EIO5I/O 錯誤硬件故障
ENOMEM12內存不足malloc、mmap
EACCES13權限被拒絕文件訪問權限不足
EINVAL22無效參數API 參數錯誤
ERANGE34結果超出範圍數學函數、轉換函數