UNIX環境編程學習筆記(1):——出錯處理errno


lienhua34
2014 年 8 月 24 日

1. errno變量

文件 <errno.h> 中定義了符號 errno 以及可以賦予它的各種常量,這些常量都是以字符 E 開頭。例如,若 errno 等於常量 EACCES,表示產生了權限問題(例如,沒有打開所要求文件的足夠權限)。


當 UNIX 函數出錯時,常常返回一個負值,而且將整型變量 errno 設置成含有附加信息的各個常量。例如,open 函數如果成功執行則返回一個非負文件描述符,如出錯則返回 -1。在 open 出錯時,有大約 15 種不同的errno 值(文件不存在、權限問題等)。

對於 errno 應該知道兩條規則。

規則一:如果沒有出錯,則errno的值不會被一個例程清除。

因此,僅當函數的返回值指明出錯時,才校驗 errno 的值。

規則二:任一函數都不會將errno的值設置為0,在<errno.h>中定義的所有常量都不為0.

出錯標志 errno 是一個整型數值,這個對於用戶提示不夠有好。C 標准定義了兩個函數,用於幫助打印出錯信息。

#include <string.h>

char *strerror(int errnum);

返回值:指向消息字符串的指針


此函數將 errnum(它通常就是 errno 值)映射為一個出錯信息字符串,並且返回此字符串的指針。

perror 函數基於 errno 的當前值,在標准出錯上產生一條出錯信息,然后返回。

#include <stdio.h>

void perror(const char *msg);

它首先輸出由 msg 指向的字符串,然后是一個冒號,一個空格,接着是對應於 errno 值的出錯信息,最后是一個換行符。

例子:

下面代碼展示了這兩個出錯函數的使用方法。

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
    fprintf(stderr, "EACCES: %s\n", strerror(EACCES));
    errno = ENOENT;
    perror(argv[0]);
    exit(0);
}

編譯該程序,生成errno_demo,然后執行它。

lienhua34:demo$ gcc -o errno_demo errno_demo.c
lienhua34:demo$ ./errno_demo
EACCES: Permission denied
./errno_demo: No such file or directory

2. 打印所有錯誤信息

C 標准庫定義了sys_nerr 用於記錄錯誤信息總個數,下面程序通過循環來打印所有信息。

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
    int idx = 0;
    for (idx = 0; idx < sys_nerr; idx++) {
        printf("Error #%3d: %s\n", idx, strerror(idx));
    }
    exit(0);
}

編譯該程序,生成print_err,然后執行它。

lienhua34:demo$ gcc -o print_err print_err.c
lienhua34:demo$ ./print_err
Error # 0: Success
Error # 1: Operation not permitted
Error # 2: No such file or directory
Error # 3: No such process
Error # 4: Interrupted system call
...
Error #133: Unknown error 133
Error #134: Unknown error 134
lienhua34:demo$

3. 多線程擴展

在支持線程的環境中,多個線程共享進程地址空間,每個線程都有屬於它自己的局部 errno 以避免一個線程干擾另一個線程。

函數 strerror() 不是線程安全的。因為該函數將 errnum 對應的字符串保存在一個靜態的緩沖區中,然后將該緩沖區的指針返回。另一個線程調用 strerror() 就會重新設置靜態緩沖區的內容。

4. 出錯恢復

可將 <errno.h> 中定義的各種出錯分成致命性的和非致命性的兩類。對於致命性的錯誤,無法執行恢復動作,最多只能在用戶屏幕上打印出一條出錯信息,或者將一條出錯信息寫入日志文件,然后終止。而對於非致命性的錯誤,有時可以較妥善地進行處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM