juh*_*ist 8 c error-handling core
我正在与其他团队成员一起在C中开发一个大型项目,我们对如何处理"这种情况永远不会发生"的错误方式存在分歧.我的意思是代码当前永远无法达到的错误情况,但有人可以修改代码,修改后可能会出现错误情况.
例如,假设我有一个函数,在成功时返回0,如果给出NULL参数则返回-EINVAL.我自然会做的是:
int err;
struct myctx ctx;
err = callFunction(&ctx);
if (err != 0)
{
abort();
}
Run Code Online (Sandbox Code Playgroud)
甚至:
int err;
struct myctx ctx;
err = callFunction(&ctx);
if (err == -EINVAL)
{
abort();
}
else if (err != 0)
{
abort();
}
Run Code Online (Sandbox Code Playgroud)
...区分-EINVAL和未知错误代码这两种情况.
这种错误处理方法的好处是编程简单(几行代码)并留下可用于快速调试情况的核心文件.
但是,一些团队成员不同意这种错误处理方法,因为我正在做一个不干净的退出,而代码当前永远不会到达abort()行,有可能在将来有人修改代码并且它到达abort()然后行.据他们说,我应该尝试做一个受控退出并将原因打印给用户.所以,我想我应该做的不是:
int err;
struct myctx ctx;
err = callFunction(&ctx);
if (err == -EINVAL)
{
fprintf(stderr, "Argument was NULL in file %s line %d\n", __FILE__, __LINE__);
exit(1);
}
else if (err != 0)
{
fprintf(stderr, "Error was %d in file %s line %d\n", err, __FILE__, __LINE__);
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这第二个错误处理策略更糟糕,因为它不会留下可用于调试此情况的核心文件.此外,它导致代码具有更多代码行.
所以,问题是,如何在C中处理"这种情况永远不会发生"的错误风格?我应该使用描述性错误消息进行中止或受控退出吗?
原则上,您应该始终处理错误并为用户生成尽可能最具解释性的描述。这是正确的做法,在日本他们称之为“honte”。
然而,在实践中,您abort()在第一个示例中未解释的内容是大多数人都会做的,因为它写起来更快。这样做的结果是,大多数应用程序在失败时都会惨遭退出。例如,当 Microsoft Word 崩溃时,向用户显示的消息是“Word 遇到问题,现在将退出”。或类似的东西。许多应用程序根本不给出任何消息,只是简单地终止。
正确的编程是对所谓的负路径进行完全编码。不仅每个可能的故障都应该生成有意义的文本消息,而且当故障返回并通过调用链向后渗透时,每个调用函数都应该将其上下文和任何相关参数添加到消息的前面。所以给用户的最终消息应该是这样的:
尝试初始化时:尝试在 [c:\user\data\configuration.ini] 加载配置文件时:无法读取第 453 行:参数值“NumRedirects”无效(越界):-43
在此错误消息中,我们看到每个函数在接收错误时都会将其上下文插入字符串的开头,后跟冒号,然后将失败返回给调用它的函数。最终结果显示所有重要信息(正在读取的文件、正在解析的行、正在加载的参数、为参数提供的无效值)。这充分向用户(或开发人员)解释了问题所在。