【问题标题】:Printing error messages打印错误信息
【发布时间】:2009-11-05 08:30:26
【问题描述】:

我只是想知道制作自定义打印错误功能的最佳方法是什么。

例如我在头文件中有一些这样的#defines:

#define SOCKET_ERR 0
#define BIND_ERR   1
#define LISTEN_ERR 2 
etc

那么也许可以这样使用:

if(/*something has gone wrong with socket*/)
{
   print_error(SOCKET_ERR);
}

print_error(int error)
{
   if(error == 0)
   {
       printf("Socket failure\n");
   }
}

但是,我认为这并不完美,我想做得更好。也许更专业一些,也许更具可扩展性。

非常感谢您的建议,

【问题讨论】:

  • 使用 'fprintf(stderr, ...)' 报告错误(或者,至少,通常写入 'stderr' 而不是 'stdout' - 或写入日志文件,或两者都记录文件和标准错误)。

标签: c


【解决方案1】:

您可以考虑使用variadic functions 进行错误报告,它们变得更加通用。

例如

#include <stdarg.h>
void my_error(FILE *out, const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vfprintf(out, fmt, ap);
    va_end(ap);
}

可以这样调用(注意,我假设是 c99 编译器):

my_error(stderr,
    "%s: Invalid range of %ld near line %d", __func__, range, __LINE__);

这可以很容易地与其他答案联系起来,表明可以在枚举列表中定义错误代码,并使用常量字符串数组来翻译它们。我将把它作为练习留给读者。很容易让上面的例子接受更多的参数。

注意:如果您使用 char buffer[LEN] 之类的东西来自定义打印字符串的格式,请将其从 void 更改为 unsigned int,让它返回 vsnprintf() 无法打印的字节数,这可能对呼叫者,召集者。上面的示例是“安全的”,您不必担心会溢出一些堆栈分配的缓冲区以及未定义长度的格式化错误消息。或者,将其保留为空并让它打印它可以打印的内容(同时注意它无法打印所有内容),这取决于您。这种方法的缺点是不太清楚可变参数一旦扩展的长度。毕竟,您报告的是意外结果:)

这种方法可以让您通过传达有意义和信息丰富的错误消息来帮助您自己,并将它们简单地记录到任何打开的文件中。

我知道这个例子基本上描述了 printf() 本身。我发布它是为了展示它是多么容易适应和扩展。

【讨论】:

  • 你好。我认为这听起来是最好的主意。您知道使用过此功能的任何链接吗?
  • 函数的 C99 名称是“__func__”而不是“__FUNCTION__”。
  • @Jonathan Leffler:是的,你是对的。我已经习惯了 glibc 的物质享受。
【解决方案2】:

查看log4c 了解如何实现日志记录的一些想法。

这里有一些建议:不要只打印“出现错误”。提供尽可能多的信息:哪个 IP 地址?错误代码?你的代码试图达到什么目的?

当您需要编写错误消息时,请问自己这个问题:当我看到此错误消息时,我需要知道什么?什么可以帮助我解决这个问题?

【讨论】:

【解决方案3】:

你也可以这样做:

//Enum for the error codes
typedef enum
{
    SOCKET_ERR = 0,
    BIND_ERR,
    LISTEN_ERR,
    LAST_ENTRY //This SHOULD be the last entry
} ErrorCode;

//Error descriptions..number of entries should match the number of entries in Enum
const char* errorDesc[] =
{
    "Socket failure",
    "Bind failure",
    "Listen failure",
    "Dummy"
};


void printError(ErrorCode c)
{
    //Validate..
    if( c < LAST_ENTRY)
    {
        printf(errorDesc[c]);
    }
}

【讨论】:

  • 大多数系统为“不是错误”保留 0。在 C99 中,您可以使用指定的初始化器,例如:[SOCKET_ERR] = "Socket failure",,它显着提高了初始化器对 errorDesc 的可靠性。
猜你喜欢
  • 2016-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
相关资源
最近更新 更多