詳解C語(yǔ)言中的錯(cuò)誤報(bào)告errno與其相關(guān)應(yīng)用方法
C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的錯(cuò)誤報(bào)告用法有三種形式。
1、errno
errno在<errno.h>頭文件中定義,如下
#ifndef errno extern int errno; #endif
外部變量errno保存庫(kù)程序中實(shí)現(xiàn)定義的錯(cuò)誤碼,通常被定義為errno.h中以E開頭的宏,
所有錯(cuò)誤碼都是正整數(shù),如下例子
# define EDOM 33 /* Math argument out of domain of function. */
EDOM的意思是參數(shù)不在數(shù)學(xué)函數(shù)能接受的域中,稍后的例子中用到了這個(gè)宏。
errno的常見用法是在調(diào)用庫(kù)函數(shù)之前先清零,隨后再進(jìn)行檢查。
在linux中使用c語(yǔ)言編程時(shí),errno是個(gè)很有用的動(dòng)動(dòng)。他可以把最后一次調(diào)用c的方法的錯(cuò)誤代碼保留。但是如果最后一次成功的調(diào)用c的方法,errno不會(huì)改變。因此,只有在c語(yǔ)言函數(shù)返回值異常時(shí),再檢測(cè)errno。
errno會(huì)返回一個(gè)數(shù)字,每個(gè)數(shù)字代表一個(gè)錯(cuò)誤類型。詳細(xì)的可以查看頭文件。/usr/include/asm/errno.h
如何把errno的數(shù)字轉(zhuǎn)換成相應(yīng)的文字說明?
一個(gè)簡(jiǎn)單的例子
#include <stdio.h> #include <errno.h> #include <string.h> #include <math.h> int main(void) { errno = 0; int s = sqrt(-1); if (errno) { printf("errno = %d\n", errno); // errno = 33 perror("sqrt failed"); // sqrt failed: Numerical argument out of domain printf("error: %s\n", strerror(errno)); // error: Numerical argument out of domain } return 0;
2、strerror
strerror在<string.h>中定義,如下
__BEGIN_NAMESPACE_STD
/* Return a string describing the meaning of the `errno' code in ERRNUM. */
extern char *strerror (int __errnum) __THROW;
__END_NAMESPACE_STD
函數(shù)strerror返回一個(gè)錯(cuò)誤消息字符串的指針,其內(nèi)容是由實(shí)現(xiàn)定義的,字符串不能修改,但可以在后續(xù)調(diào)用strerror函數(shù)是覆蓋。
char *strerror(int errno)
使用方式如下:
fprintf(stderr,"error in CreateProcess %s, Process ID %d ",strerror(errno),processID)
將錯(cuò)誤代碼轉(zhuǎn)換為字符串錯(cuò)誤信息,可以將該字符串和其它的信息組合輸出到用戶界面。
注:假設(shè)processID是一個(gè)已經(jīng)獲取了的整形ID
3、perror
perror在<stdio.h>中定義,如下
__BEGIN_NAMESPACE_STD
/* Print a message describing the meaning of the value of errno.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern void perror (const char *__s);
__END_NAMESPACE_STD
函數(shù)perror在標(biāo)準(zhǔn)錯(cuò)誤輸出流中打印下面的序列:參數(shù)字符串s、冒號(hào)、空格、包含errno中當(dāng)前錯(cuò)誤碼的錯(cuò)誤短消息和換行符。在標(biāo)準(zhǔn)C語(yǔ)言中,如果s是NULL指針或NULL字符的指針,則只打印錯(cuò)誤短消息,而不打印前面的參數(shù)字符串s、冒號(hào)及空格。
void perror(const char *s)
函數(shù)說明
perror ( )用來將上一個(gè)函數(shù)發(fā)生錯(cuò)誤的原因輸出到標(biāo)準(zhǔn)錯(cuò)誤(stderr),參數(shù)s 所指的字符串會(huì)先打印出,后面再加上錯(cuò)誤原因 字符串。此錯(cuò)誤原因依照全局變量 errno 的值來決定要輸出的字符串。
另外并不是所有的c函數(shù)調(diào)用發(fā)生的錯(cuò)誤信息都會(huì)修改errno。例如gethostbyname函數(shù)。
errno是否是線程安全的?
errno是支持線程安全的,而且,一般而言,編譯器會(huì)自動(dòng)保證errno的安全性。
我們看下相關(guān)頭文件 /usr/include/bits/errno.h
會(huì)看到如下內(nèi)容:
# if !defined _LIBC || defined _LIBC_REENTRANT /* When using threads, errno is a per-thread value. */ # define errno (*__errno_location ()) # endif # endif /* !__ASSEMBLER__ */ #endif /* _ERRNO_H */
也就是說,在沒有定義__LIBC或者定義_LIBC_REENTRANT的時(shí)候,errno是多線程/進(jìn)程安全的。
為了檢測(cè)一下你編譯器是否定義上述變量,不妨使用下面一個(gè)簡(jiǎn)單程序。
#include <stdio.h> #include <errno.h> int main( void ) { #ifndef __ASSEMBLER__ printf( "Undefine __ASSEMBLER__/n" ); #else printf( "define __ASSEMBLER__/n" ); #endif #ifndef __LIBC printf( "Undefine __LIBC/n" ); #else printf( "define __LIBC/n" ); #endif #ifndef _LIBC_REENTRANT printf( "Undefine _LIBC_REENTRANT/n" ); #else printf( "define _LIBC_REENTRANT/n" ); #endif return 0; }
- C語(yǔ)言中返回錯(cuò)誤信息的相關(guān)函數(shù)用法總結(jié)
- C語(yǔ)言創(chuàng)建鏈表錯(cuò)誤之通過指針參數(shù)申請(qǐng)動(dòng)態(tài)內(nèi)存實(shí)例分析
- C語(yǔ)言初學(xué)者代碼中的常見錯(cuò)誤與問題
- C語(yǔ)言編程時(shí)常犯十八個(gè)錯(cuò)誤小結(jié)
- C語(yǔ)言調(diào)試手段:鎖定錯(cuò)誤的實(shí)現(xiàn)方法
- 深入理解C語(yǔ)言中編譯相關(guān)的常見錯(cuò)誤
- 基于C語(yǔ)言中段錯(cuò)誤的問題詳解
- 詳解C語(yǔ)言中scanf函數(shù)使用的一些注意點(diǎn)
- C語(yǔ)言 volatile與const同時(shí)使用應(yīng)注意的問題
- 基礎(chǔ)C語(yǔ)言編程時(shí)易犯錯(cuò)誤有哪些
相關(guān)文章
Qt使用SQLite數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)增刪改查
這篇文章主要為大家詳細(xì)介紹了Qt如何使用SQLite數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)增刪改查功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-06-06C語(yǔ)言實(shí)現(xiàn)餐廳點(diǎn)餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)餐廳點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06用C語(yǔ)言求冪函數(shù)和指數(shù)函數(shù)的方法
這篇文章主要介紹了用C語(yǔ)言求冪函數(shù)和指數(shù)函數(shù)的方法,即pow()函數(shù)和sqrt()函數(shù)的使用,需要的朋友可以參考下2015-08-08VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目(圖文教程)
這篇文章主要介紹了VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03