这一节书上把它放到线程这一章,按理说应该在前面就讲了
头文件errno.h定义了变量errno,它存储了错误发生时的错误码,通过错误码可以得到错误的信息
程序开始执行时,变量errno被初始化为0。很多库函数在执行过程中遇到错误时就会将errno设置为相应的错误码。函数被成功调用时,它们不修改errno的值。因此,当一个函数被成功调用,errno的值可能不为零,它的非零值由前面的函数设置。所以不能根据errno的值来判断一个函数执行是否成功。当函数调用失败时( 函数返回-1或NULL),errno 值才有意义。
示例程序1
以下是一个示例程序,改程序通过打开一个文件,如果由于某种原因文件不能被打开时,就可以得到一个相应的errno值,检查其对应错误码,可以得到错误的原因。
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(){FILE *stream;char *filename="test";errno=0;stream=fopen(filename,"r");//这个是C语言的文件打开,和之前讲的Linux的不一样,不过效果都是一样的if(stream==nullptr)printf("open file %s failed,errno is %d\n",filename,errno);else printf("open file %s successfully\n",filename);
}
如果是文件不存在的情况下运行,结果如下
2对应的错误码是ENOENT,然后就知道错误原因是:文件或目录不存在。
错误码
错误码是定义在errno.h中的宏,通常以字母E开头,后面由一串大写字母或数字组成。
以下是一些错误码的宏,当然不可能说全记住,看看就好。
成功:
- 宏:
0
- 描述:表示操作成功完成。
通用错误:
- 宏:
EINVAL
- 描述:无效的参数。
文件相关错误:
- 宏:
ENOENT
- 描述:文件或目录不存在。
- 宏:
EEXIST
- 描述:文件或目录已存在。
内存相关错误:
- 宏:
ENOMEM
- 描述:内存不足。
权限相关错误:
- 宏:
EACCES
- 描述:权限不足。
网络相关错误:
- 宏:
ECONNREFUSED
- 描述:连接被拒绝。
- 宏:
ETIMEDOUT
- 描述:操作超时。
管道和进程相关错误:
- 宏:
EPIPE
- 描述:管道破裂。
socket 相关错误:
- 宏:
EADDRINUSE
- 描述:地址已经在使用中。
- 宏:
EADDRNOTAVAIL
- 描述:地址不可用。
IO 相关错误:
- 宏:
EIO
- 描述:IO 错误。
数学库相关错误:
- 宏:
EDOM
- 描述:域错误。
- 宏:
ERANGE
- 描述:结果太大,无法表示。
线程相关错误:
- 宏:
EPERM
- 描述:操作不允许。
信号相关错误:
- 宏:
EINTR
- 描述:被中断的系统调用。
错误的提示信息
出现错误时,可以打印出相应的错误提示信息。
strerror函数
#include<string.h>
char *strerror(int errnum);
这个函数在头文件string.h中声明。它会根据参数errnum提供的错误码获取一个描述错误信息的字符串,函数的返回值为指向该字符串的指针。errnum的值通常就是errno。
perror函数
这个函数我好早之前就介绍过了,《Linux C编程实战》笔记:文件读写-CSDN博客
#include<stdio.h>
void perror(const char *message);
perror()打印错误信息到stderr, stderr 在Linux中通常就是指屏幕或命令行终端。调用perror()时,
如果参数message是一个空指针,perror 仅仅根据errno打印出对应的错误提示信息。如果提供一
个非空的值,perro会把此message加在其输出信息的前面。perror会添加一个冒号和空格message
和错误信息分开,以便区分。
示例程序2
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
FILE *open_file(const char *filename){FILE *stream;errno=0;stream=fopen(filename,"r");if(stream==nullptr){printf("can not open the file %s. reason:%s\n",filename,strerror(errno));//用strerror获得错误的信息exit(-1);}else return stream;
}
int main(){const char *filename="test";open_file(filename);return 0;
}
strerror实际上就是通过之前的错误码得到错误码对应的错误信息字符串,然后打印出来。