目录
0.unix编程中实现简单的ls命令中使用err_sys出错处理函数的使用
1.void err_ret(const char *fmt,...)
2.void err_sys(const char *fmt,...)
3.void err_cont(int error,const char *fmt,...)
4.void err_exit(int error,const char *fmt,...)
5.void err_dump(const char *fmt,...)
6.void err_msg(const char *fmt,...)
7.void err_quit(const char *fmt,...)
8.static void err_doing(int errnoflag,int error,const char*fmt,va_list ap)
- unix高级编程中标准出错例程
前言
本文章提供了一套处理unix编程出错的函数,用于处理unix高级编程学习笔记中大多数实例以及各种出错情况,以err_开头,并向标准错误输出一条出错消息,之所以提供自己的出错函数,是为了能够写出只有一行的C代码出错处理程序。
一、函数可变参数的介绍
我们使用va_start和va_end来处理可变的函数参数,其处理的核心思想是,参数个数可变,但参数类型可知,用format指出参数的类型。在下面的出错函数中err_ret(const char *fmt,...);定义了一个typedef char* va_list的字符指针ap,通过调用va_start(ap,fmt);对ap进行初始化,ap指向参数列表,fmt指向可变参数表里面的第一个参数。在程序处理完成后有必要把这个ap指针关掉,以避免发生危险,通过调用va_end(ap)实现。
二、出错处理函数
0.unix编程中实现简单的ls命令中使用err_sys出错处理函数的使用
代码如下(示例):
void unix_1_3_ls(char *directory)
{
DIR *dp;
struct dirent *dirp;
if((dp = opendir(directory)) == NULL)
err_sys("can't open %s",directory);
while((dirp=readdir(dp)) != NULL)
printf("%s\n",dirp->d_name);
closedir(dp);
exit(0);
}
1.void err_ret(const char *fmt,...)
非致命错误,与系统调用相关,打印消息并且返回
void err_ret(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(1,errno,fmt,ap);
va_end(ap);
}
2.void err_sys(const char *fmt,...)
致命错误,与系统调用相关,打印错误并且使终止进程
void err_sys(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(1,errno,fmt,ap);
va_end(ap);
exit(1);
}
3.void err_cont(int error,const char *fmt,...)
非致命错误,与系统调用无关,作为显式参数传递的错误代码,打印错误消息并且退出
void err_cont(int error,const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(1,error,fmt,ap);
va_end(ap);
}
4.void err_exit(int error,const char *fmt,...)
致命错误,与系统调用无关,作为显示参数传递错误代码,打印错误消息并且终止进程
void err_exit(int error,const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(1,error,fmt,ap);
va_end(ap);
exit(1);
}
5.void err_dump(const char *fmt,...)
致命错误,与系统调用相关,打印错误消息,dump内核,终止进程
void err_dump(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(1,errno,fmt,ap);
va_end(ap);
abort();
exit(1);
}
6.void err_msg(const char *fmt,...)
非致命错误,与系统调用无关,打印错误消息并且返回
void err_msg(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(0,0,fmt,ap);
va_end(ap);
}
7.void err_quit(const char *fmt,...)
致命错误,与系统调用无关,打印错误消息,终止进程
void err_quit(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doing(0,0,fmt,ap);
va_end(ap);
exit(1);
}
8.static void err_doing(int errnoflag,int error,const char*fmt,va_list ap)
打印消息,返回到调用函数
static void err_doing(int errnoflag,int error,const char*fmt,va_list ap)
{
char buf[MAXLINE];
vsnprintf(buf,MAXLINE-1,fmt,ap);
if(errnoflag)
snprintf(buf+strlen(buf),MAXLINE-strlen(buf)-1,": %s",strerror(error));
strcat(buf,"\n");
fflush(stdout);
fputs(buf,stderr);
fflush(NULL);
}
总结
通过使用自己的出错处理函数,可以使得代码更加简洁,例如用if(出错条件)err_dump(带任意参数的printf格式);代替if(出错条件){char buf[200];sprintf(buf,带任意参数的printf格式);perror(buf);abort();}。