是否有理由在错误处理的代码中不广泛看到错误?

Is there a reason why perror isn't widely seen in code for error handling?

本文关键字:错误 代码 有理由 处理 是否      更新时间:2023-10-16

查看堆栈溢出或其他地方的代码,似乎我很少看到perror()用于报告错误的确切性质。 printf 更为常见。这是否表明错误或缺少错误?我希望它能更频繁地使用,因为它提供了更好的信息。

我个人更喜欢strerror()它做大致相同的事情,但允许您将错误消息与 printf 或类似函数一起使用,从而进一步有用 [对程序员或程序的用户,具体取决于错误类型]。

例如:

errno = 0;
FILE *f = fopen(argv[1], "rb");
if (!f)
{
    fprintf(stderr, "File %s open failed: error code %d ('%s')n", 
            argv[1], errno, strerror(errno));
    exit(1);
}

这样,我们也知道哪个文件(假设它是一个复制文件的程序,perror 不一定会告诉你它是"源"还是"去")。

如果错误是由于编程错误[或"预计不会出错的东西"],你也可以做这样的事情:

#define UNEXPECTED(cond) do { if (cond) { do_unexpected(errno, #cond, __FILE__, __LINE__); } while(0)
void do_unexpected(int err, const char* cond, const char *file, int line)
{
    fprintf(stderr, "Unexpected error %s [errno=%d, errstr=%s] at %s:%d", 
            cond, err, strerror(errno), file, line);
    exit(1);
}
errno = 0;
FILE *config = fopen("config.txt", "r");
UNEXPECTED(!config); 
... 

这是假设你不希望删除"config.txt",例如[总的来说,这是非常糟糕的编程,但也许有一个正当的理由......]

perror() 不会准确地给出发生错误的行号,而 printf() 会帮助你识别打印它的确切行。所以我认为它在调试中更有帮助,我知道的 perror() 没有任何问题......

如果在进行标准库调用之前将errno设置为零,并且该调用失败,并且它是使用errno来描述失败原因的调用之一,则perrorstrerror可能会提供有用的解释。大多数人不注意errno,更不用说如何正确使用它了。这是一个更简单时代的人工制品。

由于我使用的是C++,所以我不使用printf()和co,并且经常在启动时调用sync_with_stdio(false)。此外,该函数的问题在于它只允许在本地打印错误。我经常遇到的是这样的:

// setting errno
if(!foo1(bar))
    throw_errno_exception("foo1");
// returning errorcode
if(int e = foo2(bar))
    throw_exception(e, "foo2");

首先,并非每个函数都使用 errno。特别是对于新代码,我也不会这样做,而只是返回带有相应错误代码的int。因此,对于这些"新"功能,我必须在使用之前手动设置 errno perror() .但是,我也不想这样,因为失败的函数和我捕获异常的地方之间通常存在相当大的差距。

现在,在 C 中,您无法像C++异常那样将其他信息传递到堆栈中。出于这个原因,在 C 中记录实际失败的函数以及它失败的位置的任何上下文更为重要。