C中如何自定义报错消息?

作者: Leon_Geo | 来源:发表于2019-03-05 10:35 被阅读31次

在C语言库中有一系列的库函数和变量使得我们在编程中更加方便的以自定义的格式输出存在系统调用期间发生的错误。其中strerror和error函数是最常用的错误报告类库函数;变量program_invocatoin_short_name可以使你更加便利的获取发生错误的程序名。

1 char * strerror(int errnum)

该函数声明在string.h中,参数errnum通常取errno,函数会根据不同的errno值,返回指向特定错误消息的字符串指针。需要注意的是,你不可以私自修改这些字符串,而且如果后来有新的错误发生,这些字符串将被新的错误字符串所覆盖。

1.1 char *strerror_r(int errnum,char *buf,size_t n)

该函数作为GNU C的扩展,声明在string.h中。
因为strerror函数用来存储错误消息的内存是各进程共享的,所以随着后续错误的发生,它会不断被刷新覆盖。

为了弥补这种缺陷,我们可以使用strerror_r函数。它有三个参数,其中errnum代表错误代码,buf代表用户自定义的存储错误消息的缓存地址,n代表缓存大小。这样,在多进程编程中,我们就可以永久存储错误消息以供后续查看,而不需要担心被覆盖。

2 void * perror(const char * message)

该函数声明在stdio.h中,它向标准错误流stderr输出错误消息;

如果参数message为空或指向一个空字符串,则函数仅输出系统的错误消息;如果message不为空,则函数先输出参数指向的字符串,再添加一个冒号和空格符后,再输出系统错误消息。

program_invocation_name

strerror和perror函数产生完全相同的错误消息,而且描述的相当简单,仅有一行。有时候不能完全满足我们的需要。为此,我们引入了program_invocation_name 等变量。该变量等同于argv[0],表示不带目录的程序名。

另一个与他相似的变量为program_invocation_short_name, 它也同样代表了不含目录的程序名,只不过它更短,仅仅保留了最后一个'/'后的字符串。

#define _GNU_SOURCE

#include <error.h>
#define <stdio.h>
#define <stdlib.h>
#define <string.h>

FILE * open_sesam(char *file_name)
{
    FILE *stream;
    errno = 0;
    stream = fopen(file_name,"r");
    if(stream == NULL){
        fprintf(stderr,"%s:Couldn't open file %s:%s\n",\
 program_invocation_short_name,file_name,strerror(errno));
    exit(EXIT_FAILURE);
}
else
    return stream;
}

3 void error(int status,int errnum,const char *format,...)

有时候,我们在遇到一些错误时,并不是想让程序立即终止,而是希望它记下错误后,继续运行。此时就不得不用error函数了。

error首先输出程序名,默认通过全局变量program_name获得。但如果程序中,用户给全局函数指针变量error_print_program赋了非零值,那么error将自动通过它来调用用户自定义的函数来显示函数名;接着函数输出一个冒号加空格符,之后按照format格式输出用户自定义的字符串;如果errnum非0的话,接着函数再输出冒号加空格,之后再输出系统错误消息。

最后再来看看status参数。当它为非0时,error函数再输出完提示消息后,接着就调用exit函数返回status并退出。;如果status为0,则error函数会再输出完提示消息后正常返回,同时,全局变量error_message_count加1,程序并不终止。

3.1 void error_at_line(int status,int errnum,const char *fname,unsigned lineno,const char *format,...)

该函数与刚刚介绍的error函数非常类似,唯一的不同就是多了fname和lineno参数。它们的输出位置位于程序名之后,格式化字符串之前,主要作用是用来定位发生错误的位置。

这里又要介绍一个全局变量,error_one_per_line。它仅仅影响函数error_at_line。如果它被设置为非0值,那么当同一行发生多个错误时,文件名和行号将不会重复输出。

该函数的退出机制同error,在此就不在赘述。

下面看一个例子:

{
    char *line = NULL;
    size_t len = 0;
    unsigned lineno = 0;
    error_message_count = 0;
   while(! feof_unlocked(fp)){
        size_t n = getline(&line,&len,fp);
        if(n<=0)
            break;//End of file or error
        ++lineno;

/*process the line*/
...

    if(detected error in line)
        error_at_line(0,errno,filename,lineno,\
        "some error test %s",some_varible);
    }
    if(error_message_count != 0)
        error(EXIT_FAILURE,0,"%u errors found",error_message_count);
}

===========我是华丽的分割线===========


更多知识:
点击关注专题:嵌入式Linux&ARM

或浏览器打开:https://www.jianshu.com/c/42d33cadb1c1

或扫描二维码:

相关文章

  • C中如何自定义报错消息?

    在C语言库中有一系列的库函数和变量使得我们在编程中更加方便的以自定义的格式输出存在系统调用期间发生的错误。其中st...

  • c和c++比较

    1. 类型增强 c语言中这样可以通过编译,c++中这样会报错 c++需要改为 tips:如何查看const修饰的范...

  • iOS学习笔记

    1.在OC中向一个nil对象发送消息会发生什么?在Objective-C中向nil对象发送消息不会报错,只是在运行...

  • RocketMQ消息发布报错:No accessKey is c

    No accessKey is configured 本来这个错误是很简单个错误,本意是mq上边开启了acl验证机...

  • INSTALL_FAILED_DUPLICATE_PERMISS

    1,报错信息 2,通常自定义权限重复导致的我看到代码中的自定义权限 注释该部分代码后运行 3,新的报错日志 原因分...

  • 自定义消息

    基于窗体应用程序使用自定义的消息 在头文件中定义消息编号 WM_USER以下的消息都是系统消息,所以自定义消息时,...

  • RabbitMQ之消息重试

    消费端在处理消息过程中可能会报错,此时该如何重新处理消息呢?一般来说RabbitMQ有个方法channel.bas...

  • 自定义轮播消息控件(自定义属性,onDraw,重写Animati

    自定义轮播消息控件(自定义属性,onDraw,重写Animation等) 最近,项目要求,在大屏中,显示推送的消息...

  • uniapp在main.js 报错提示 Vue.componen

    今天打算使用uniapp的自定义组件,但是按照vue的全局注册方式,却报错【在main.js 总是提示 Vue.c...

  • Android:解决style文件不能使用自定义属性

    今天写自定义View的时候,布局文件中属性太多,想放到style中,但是遇到一个问题,就是自定义属性不识别,报错如...

网友评论

    本文标题:C中如何自定义报错消息?

    本文链接:https://www.haomeiwen.com/subject/zvpwuqtx.html