在C语言里头,errno.h头文件主要是用来报告以及检查错误状态的,支持错误处理的那些库函数要是执行失败了,就会借助全局变量errno去保存错误码,以此来告知到底出了啥问题,在使用C语言库函数,像是输入输出、数学运算或者是系统调用的时候,这个错误处理机制能够带来额外的信息用以帮助处理。
errno功能说明
在C语言里,当把头文件errno.h包含进来时,会有一个线程安全的整型变量errno被引入,这个变量存着系统函数运行失败时的错误码。
对于errno变量来说,具有如下特点。
在程序启动这个时候,errno被初始化成为0,在程序运行的进程当中,也能够自行去设置清零,以此来确保不会对后续的判断造成影响。在多线程里面,errno属于线程局部的变量(POSIX标准做了要求,是TLS),每一个线程的errno都是相互独立的,并且开销极其的小,适宜频繁地进行使用。对于C语言库函数而言,只有明确声明失败会对errno进行设置的时候,检查errno才会有效果,如果函数执行是成功的,那么都不会去改变errno的值。当库函数执行失败之时呀(返回值为 -1 或者 NULL 的情形),那便会把 errno 设置成为一个并非零的错误码呢;能够直接去读取 errno 以判别错误的类型哟,并且借助 stderror 函数来输出错误的信息哩。
关于errno支持的错误码,其宏定义和错误信息如下所示。
错误码
错误信息
举例说明
EPERM
没有权限 (Permission denied)
尝试执行一个没有权限的操作
ESRCH
找不到进程 (No such process)
尝试操作一个不存在的进程
EINTR
函数遇上信号,从而被中断,此为被中断的函数。
函数被信号中断
ENXIO
文件系统不支持
尝试打开一个不支持的块设备
EDOM
参数超出定义域 (Domain Error)
给sqrt函数传入负数
ERANGE
结果超出范围 (Range Error)
浮点数运算结果溢出
ESIGNUM
非法信号 (Invalid Signal)
尝试发送一个非法信号
EINVAL
非法参数 (Invalid Argument)
尝试使用一个非法参数
EILSEQ
不符合规定的字符排列顺序,展现出不合法的字符排列串。
尝试读取一个非法字符序列
EACCES
权限被拒绝 (Permission denied)
尝试写入一个只读文件
ENOENT
文件或目录不存在
打开一个不存在的文件
ENOMEM
内存不足
malloc 函数 申请内存失败
EIO
输入/输出错误
读写设备时发生错误
在不同系统里,错误码所对应的具体数值,有可能存在差异,于是,在程序当中,运用宏定义来进行判断,而不是直接去比较数值。
errno的使用方法
当C标准函数处理失败之际,errno主要用以处理有可能碰到的错误,此外,还能够运用stderror或者perror函数输出确切的错误信息。
这里拿文件打开函数fopen当作例子,来讲一讲errno的使用方式。
plaintext
#include
#include
#include
int main(int argc, char *argv[])
{
FILE *fp = fopen("file.txt", "r"); // -ENOENT错误
if (fp == NULL) {
printf("fopen error: %d\n", errno);
printf("fopen error: %s\n", strerror(errno));
return -1;
}
fclose(fp);
return 0;
}
运行结果如下所示。
能够瞧见,在fopen函数运行失败之际,会返回NULL,并且还会将errno设置为-ENOENT,也就是文件或者目录不存在。此时能够借助检查errno值,输出详尽的错误信息。
errno变量当作辅助办法,在那些支持错误处理的库函数运行失败之际,能够给出额外的错误讯息,助力定位问题,于开发阶段,errno可用于错误诊断、调试等情形,很值得学习掌握。