關於errno與perror,strerror函式

2021-06-28 08:56:21 字數 1184 閱讀 9350

為什麼,要強調errno看起來好像是乙個整形變數呢?因為有的標準(如iso c)只規定了errno的作用,而沒有規定它的實現方式,它可能被定義成乙個變數,也有可能被定義成乙個巨集,這個具體要看編譯器自己的實現。早些時候,posix.1曾把errno定義成extern int errno這種形式,但現在這種方式比較少見了。因為以這種形式來實現errno,在多執行緒環境下errno變數是被多個執行緒共享的,這樣可能執行緒a發生某些錯誤改變了errno的值,執行緒b雖然沒有發生任何錯誤,但是當它檢測errno的值的時候,執行緒b會以為自己發生了錯誤。所以現在errno在linux中被實現成extern int * __errno_location(void): #define errno (*__errno_location()),這樣每個執行緒都有自己的errno,不會再發生混亂了。

perror和strerror函式都是用來列印錯誤提示資訊的,它們的原型分別是:

char *strerror(int errnum);

它返回errnum的值所對應的錯誤提示資訊,例如errnum等於12的話,它就會返回"cannot allocate memory"。

void  perror(const char *s);

它先列印s指向的字串,然後輸出當前errno值所對應的錯誤提示資訊,例如當前errno若為12,呼叫perror("abc"),會輸出"abc: cannot allocate memory"。

關於errno有三點需要特別注意:

1、如果系統呼叫或庫函式正確執行的話,errno的值是不會被清零

(置0,注意這裡是不會被清零,不是不會被改變)的,假若執行函式a的時候發生了錯誤errno被改變,接下來直接執行函式b,如果函式b正確執行的話,errno還保留函式a發生錯誤時被設定的值。所以,在利用errno之前,最好先對函式的返回值進行判斷,看是否發生了錯誤,返回值錯誤再利用errno判斷時**發生了錯誤。所以如果乙個函式無法從返回值上判斷正誤,而只能通過errno來判斷出錯,那你在呼叫它之前

必須手動將errno清零

2、系統呼叫或庫函式正確執行,並不保證errno的值不會被改變!

3、任何錯誤號(即發生錯誤時errno的取值)都是非0的。

綜上所述,當需要用errno來判斷函式是否正確執行的時候,最好先將errno清零,函式執行結束時,通過其返回值判斷函式是否正確執行,若沒有正確執行,再根據errno判斷時**發生了錯誤。

關於errno與perror,strerror函式

為什麼,要強調errno看起來好像是乙個整形變數呢?因為有的標準 如iso c 只規定了errno的作用,而沒有規定它的實現方式,它可能被定義成乙個變數,也有可能被定義成乙個巨集,這個具體要看編譯器自己的實現。早些時候,posix.1曾把errno定義成extern int errno這種形式,但現...

關於 errno的使用

errno 是乙個全域性的變數,在 errno.h 中有它的定義 if defined mt defined dll defined mac crtimp extern int cdecl errno void define errno errno else ndef mt ndef dll crt...

關於errno標頭檔案

看見網上很多地方都用到這個標頭檔案,一直不理解,今天找了一些資料,可以方便自己理解 errno是乙個巨集,它定義在對應的標頭檔案裡面,這個在上面的鏈結裡也有說到 errno是乙個全域性變數,它儲存了最近一次的錯誤。我常看見的乙個 是 errno eexisteexist的中文翻譯是錯誤已經存在 也就...