程序中的错误处理
为什么是errno
$ main 3 fopen #/return value 如果fopen调用失败返回NULL, 并且errno的值被用来标识错误
....
Upon successful completion fopen(), fdopen() and freopen() return a
FILE pointer. Otherwise, NULL is returned and errno is set to indicate
the error.
....
全局变量errno
- 系统与定义了一个整型的全局变量errno. 在库函数和系统调用出错的时候, 可以设置errno的值, 然后根据errno的值找到描述错误的字符串.
- 头文件errno.h中包含对errno全局变量的外部声明和各种错误号的宏定义, 错误的描述信息.
1. strerror(3) 根据错误的编号获取错误的描述信息
// mian 3 strerror 都可以查看到这些信息
#include <string.h>
char *strerror(int errnum)
- 功能: 返回错误编号对应的描述错误的字符串
- 参数:
- errnum: 错误的编号
- 返回值:
- 找不到错误的编号, 返回 “Unknown error nnn” 字符串的首地址
- 找到错误的编号, 返回描述错误的字符串的首地址
代码示例strerror的使用
file.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[]){
FILE *fn=fopen(argv[1],"r");
if (fn==NULL){
printf("fopen failed...%d\n", errno);
printf("%s\n", strerror(errno));
return -1;
}
printf("fopen success...\n");
fclose(fn);
fn=NULL;
return 0;
}
$ gcc file.c
$ ./a.out a
fopen failed...2
No such file or directory
$ touch a
$ ./a.out a
fopen success...
2. perror
- 通过标准错误输出显示最近一次函数调用的错误信息
#include <stdio.h>
void perror(const char* s);
- 功能: 输出最近一次函数调用的错误信息
- 参数: s 用户自定义的字符串
- 返回值: 该函数不返回
- 注意: 先输出参数s的内容, 然后输出":" 和 空格, 描述错误的信息, 换行符
file.c
#include <stdio.h>
int main(int argc, char *argv[]){
FILE *fn=fopen(argv[1],"r");
if (fn==NULL){
perror("fopen");
return -1;
}
printf("fopen success...\n");
fclose(fn);
fn=NULL;
return 0;
}
$ rm b
$ ./a.out b
fopen: No such file or directory
$ touch b
$ ./a.out b
fopen success...
3. 扩展
perror以后会经常用到, 不如直接把它封装成自己的宏, 以后使用起来会方便许多
t_stdio.h
#ifndef T_STDIO_H_
#define T_STDIO_H_
#include <stdio.h>
#define E_MSG(STRING, VAL) do{perror(STRING); return(VAL);}while(0)
#endif
file.c
#include "t_stdio.h" // 如果 mv t_stdio.h /usr/include/. 那么这句可以换成 #include <t_stdio.h>
int main(int argc, char *argv[]){
FILE *fn=fopen(argv[1],"r");
// if (fn==NULL){
// perror("fopen");
// return -1;
// }
// printf("fopen success...\n");
// fclose(fn);
if(fn==NULL)E_MSG("fopen", -1);
// 这里用文件
printf("fopen success...\n");
fclose(fn);
fn=NULL;
return 0;
}
$ gcc -c file.c
$ a.out h
fopen: No such file or directory
$ touch h
$ a.out h
fopen: Success
$ gcc -E file.c #预处理宏以后的结果
....
do{perror("fopen"); return(-1);}while(0);
....