程序错误是指在软件运行中因为程序本身有错误而造成的功能不正常、死机、数据丢失、非正常中断等现象。错误处理程序是指软件系统中用于处理错误的程序。在编程语言中,错误处理模型一般可以分为:返回值模型、全局错误标志模型、恢复性模型和限制性模型。本文主要介绍C语言中异常错误处理及日志记录。

1、C语言的错误处理

其它编程语言中,例如,C++,Java,C#,Python等语言中,都可以使用try catch类似语法进行异常处理。C语言中没有异常机制,一般用返回值标识错误,判断返回值进行错误的处理。

返回值表示出错的常见情况可能如下:

1)如果函数返回值是int ,并且返回的数据不可能是负数,直接返回-1表示出错,非负数代表正常返回数据。

2)如果函数返回值是int ,但返回的数据也可能是负数;返回0代表正常,-1代表出错。用指针类型的参数带出返回的数据。

3)如果函数返回值是指针类型,返回NULL(0)代表出错,其他代表正常。

4)如果函数不需要考虑出错情况,可以用void返回值。

2、错误异常处理函数及全局变量

C标准中,对于错误处理提供了一个全局变量和3个函数:

1)全局变量

errno:外部的全局变量,用于储存错误的编号。

2)异常错误处理函数

strerror()perror()printf() 都可以把错误的编号转换成错误的信息。

strerror():传入一个错误的编号,返回一个错误的信息

perror():打印当前的错误信息(自动查找errno得到的错误编号)

printf("%m"):打印当前错误信息(自动查找errno)

例如,

#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ;
int main ()
{
   FILE * pf;
   int errnum;
   pf = fopen ("cjavapy.txt", "rb");
   if (pf == NULL)
   {
      errnum = errno;
      fprintf(stderr, "错误号: %d\n", errno);
      perror("通过 perror 输出错误");
      fprintf(stderr, "打开文件错误: %s\n", strerror( errnum ));
   }
   else
   {
      fclose (pf);
   }
   return 0;
}

3、程序退出状态值

通常情况下,程序成功执行完一个操作正常退出的时候会带有值 EXIT_SUCCESS。在这里,EXIT_SUCCESS 是宏,它被定义为 0

如果程序中存在一种错误情况,当退出程序时,会带有状态值 EXIT_FAILURE,被定义为 -1

例如,

#include <stdio.h>
#include <stdlib.h>
main()
{
   int dividend = 20;
   int divisor = 5;
   int quotient;
   if( divisor == 0){
      fprintf(stderr, "除数为 0 退出运行...\n");
      exit(EXIT_FAILURE);
   }
   quotient = dividend / divisor;
   fprintf(stderr, "quotient 变量的值为: %d\n", quotient );
   exit(EXIT_SUCCESS);
}

4、日志记录

C语言中记录日志能帮助程序员在程序开发时调试、记录及监控数据。程序在正式运行时,也方便能过日志来排查问题。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
enum {ERROR,WARNING,INFO,DEBUG};
//宏定义形式
#define LogRecord(_error_level,_fmt,_X...) \
    do { \
        time_t _current_time=time(NULL); \
        char _file_name[256]="\0"; \
        strftime(_file_name,sizeof(_file_name),"%Y-%m-%d_log_record.log",localtime(&_current_time)); \
        FILE *_fp=NULL; \
        _fp=fopen(_file_name,"a+"); \
        if(_fp!=NULL) \
        { \
            char _time_str[32]; \
            strftime(_time_str,sizeof(_time_str),"%Y-%m-%d %H:%M:%S",localtime(&_current_time)); \
            if(_error_level==ERROR) \
            { \
                fprintf(_fp,"[%s]-[%s]-[%s]-[%d] :> "_fmt"\n",_time_str,"ERROR",__FILE__,__LINE__,##_X); \
            } \
            else if(_error_level==WARNING) \
            { \
                fprintf(_fp,"[%s]-[%s]-[%s]-[%d] :> "_fmt"\n",_time_str,"WARNING",__FILE__,__LINE__,##_X); \
            } \
            else if(_error_level==INFO) \
            { \
                fprintf(_fp,"[%s]-[%s]-[%s]-[%d] :> "_fmt"\n",_time_str,"INFO",__FILE__,__LINE__,##_X); \
            } \
            else if(_error_level==DEBUG) \
            { \
                fprintf(_fp,"[%s]-[%s]-[%s]-[%d] :> "_fmt"\n",_time_str,"DEBUG",__FILE__,__LINE__,##_X); \
            } \
            fclose(_fp); \
        } \
    }while(0);
//函数形式
void log_reocrd(int error_level, const char *format, ...)
{
    va_list args;
    FILE *fp=NULL;
    char time_str[32];
    char file_name[256];
    va_start (args, format);
    time_t time_log = time(NULL);
    strftime(file_name,sizeof(file_name),"%Y-%m-%d_log_history.log",localtime(&time_log));
    if((fp=fopen(file_name,"a+"))!=NULL)
    {
        strftime(time_str,sizeof(time_str),"%Y-%m-%d %H:%M:%S",localtime(&time_log));
        if(error_level==(int)ERROR)
        {
            fprintf (fp, "[%s]-[%s]-[%s]-[%d] :> ",time_str,"ERROR",__FILE__,__LINE__);
            vfprintf (fp,format,args);
            fprintf (fp,"\n");
        }
        else if(error_level==(int)WARNING)
        {
            fprintf (fp, "[%s]-[%s]-[%s]-[%d] :> ",time_str,"WARNINGs",__FILE__,__LINE__);
            vfprintf (fp,format,args);
            fprintf (fp,"\n");
        }
        else if(error_level==(int)INFO)
        {
            fprintf (fp, "[%s]-[%s]-[%s]-[%d] :> ",time_str,"INFO",__FILE__,__LINE__);
            vfprintf (fp,format,args);
            fprintf (fp,"\n");
        }
        else if(error_level==(int)DEBUG)
        {
            fprintf (fp, "[%s]-[%s]-[%s]-[%d] :> ",time_str,"DEBUG",__FILE__,__LINE__);
            vfprintf (fp,format,args);
            fprintf (fp,"\n");
        }
        fclose(fp);
    }
    va_end (args);
}
int main()
{
    int i=10;
    double x=3.1415926;
    long long k=123144345;
    LogRecord(INFO,"i=%d",i)
    LogRecord(INFO,"x=%lf",x)
    LogRecord(INFO,"k=%lld",k)
    LogRecord(INFO,"cjavapy")
    LogRecord(INFO,"www.cjavapy.com",NULL)
    log_reocrd(INFO,"i=%d",i);
    log_reocrd(INFO,"x=%lf",x);
    log_reocrd(INFO,"k=%lld",k);
    log_reocrd(INFO,"cjavapy");
    log_reocrd(INFO,"www.cjavapy.com",NULL);
    printf("%s","finish");
    return 0;
}

推荐文档