查看stackoverflow或其他地方的代码,似乎我很少看到perror()用于报告错误的确切性质。 printf更常见。这是一个指示perror有什么错误或缺失的指标吗?我希望它可以更频繁地使用,因为它可以提供更好的信息。
答案 0 :(得分:7)
我个人更喜欢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);
}
这样,我们也知道WHICH文件(说它是一个复制文件的程序,perror不一定会告诉你它是“源”还是“destionation”)。
如果错误是编程错误[或“预计不会出错的东西”],你也可以这样做:
#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”,作为一个例子[一般情况下编程非常糟糕,但也许有正当理由......]
答案 1 :(得分:2)
perror()不会准确地给出发生错误的行号,而printf()会帮助您识别打印时的确切行。所以我认为它在调试方面更有帮助,我知道的perror()并没有错......
答案 2 :(得分:1)
如果在进行标准库调用之前将errno
设置为零并且该调用失败并且是使用errno
来描述失败原因的调用之一,那么perror
和{ {1}}可能会提供有用的解释。大多数人不关注strerror
,更不用说如何正确使用它了。这是一个更简单的时间的神器。
答案 3 :(得分: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
。因此,对于那些“新”函数,我必须在使用perror()
之前手动设置errno。但是,我也不希望这样,因为失败的函数和我捕获异常的地方之间通常存在相当大的差距。
现在,在C中,您无法像在C ++异常中那样在堆栈中传递其他信息。因此,在C中更重要的是记录实际失败的函数以及它失败的地方的任何上下文。