7

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

4

4 回答 4

8

我个人更喜欢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”作为示例[这通常是非常糟糕的编程,但也许有一个正当的理由......]

于 2013-01-23T16:31:24.503 回答
2

perror() 不会准确地为您提供发生错误的行号,而您的 printf() 将帮助您识别正在打印的确切行。所以我认为它对调试更有帮助,我所知道的 perror() 没有错......

于 2013-01-23T16:19:36.827 回答
1

如果您errno在进行标准库调用之前设置为零并且该调用失败并且它是errno用于描述其失败原因的调用之一,那么perror并且strerror可能会提供有用的解释。大多数人不注意errno,更不用说如何正确使用它了。这是更简单时代的产物。

于 2013-01-23T16:43:29.837 回答
0

由于我使用的是 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()。但是,我也不希望这样,因为失败的函数和我捕获'n'记录异常的地方之间通常有很大的差距。

现在,在 C 中,您无法像在 C++ 异常中那样将附加信息向上传递。出于这个原因,在 C 中记录实际失败的函数和失败位置的任何上下文更为重要。

于 2013-01-23T17:39:09.167 回答