返回介绍

7.5 回归基础

发布于 2024-08-19 12:44:37 字数 4546 浏览 0 评论 0 收藏 0

从根本上讲,我认为 C++ 需要两种错误处理机制:

  • 异常——罕见的错误或直接调用者无法处理的错误。
  • 错误码——错误码表示可以由直接调用者处理的错误(通常隐藏在易于使用的检测操作中或作为 (值,错误码) 对从函数返回)。

考虑代码:

void user()
{
    vector<string> v{"hello!"};
    for (string s; cin>>s; )
        v.push_back(s);
    auto ps = make_unique<Shape>(read_shape(cin));
    Smiley_face face{Point{0,0},20};
    // ...
}

这个例子是人造的,但其编程风格并非不典型。我们可以从中看出,user() 函数里有很多发生不太可能的错误的可能性:内存耗尽、读取错误、构造失败(例如,在 Smile_face 的多层次结构中出现错误等)。另外,使用 unique_ptr<Shape> 可以防止内存泄漏。如果我们使用显式错误码而不是异常,那么这个函数中至少需要进行五次错误检查,源代码数量将翻倍,并需要在各个构造函数中进行更多检 查。没有 RAII(及其与异常的集成),代码将进一步膨胀。一般来说,更多的代码意味着更多的错误。当添加的代码使控制流程复杂时,尤其如此。这一点经常被那些通 过小例子论证的人所忽视。对于小例子来说,就一项测试关系不大,相对也很难漏掉。

另一方面,有些错误是预料得到的,我们更愿意使用某种形式的错误码来对其进行检查:

ifstream f {"Myfile"};
if (!f) {
    // ... 处理错误 ...
}
// ... 使用 f ...

在这里,为方便起见,错误码隐藏在输入流的状态里。

因此,在理想情况下,应该只有两种错误处理的方法,但是我真的不知道如何达到这样一种理想状态。仅仅 (值,错误码) 对就有十几种变体被广泛使用(例如 std::map::insert()), 并且还有一些新的变体也在 2011 年的 WG21 中被讨论(如 [Botet and Bastien 2018; Sutter 2018b])。即使委员会能就其中一个方案达成一致,也仍然会有至少十几个广泛使用的错误处理方案,每个方案都有一大群忠实的追随者支持,许多方案都有 数百万行难以更动的代码。

很少有关于异常的性能和 C++ 中返回码可靠性的认真研究([Renwick et al. 2019] 是一个例外)。但是,有许多不科学的小研究和许多大声表达的意见——常常声称异常天生就比各种形式的错误码检查慢。这与我的经验不符。就我所知,还没有任 何严谨的研究发现在现实的例子中错误码能胜出很多,或者异常能胜出很多。在这一讨论场景下,很多表示整数倍的差异,而不是几个百分点。

运行一个简单的性能测试:进行一个 N 层深度的调用序列,然后报告错误。如果错误很少见,例如 1:1000 或 1:10000 的错误率,并且调用嵌套很深,例如 100 或 1000,则异常处理要比明确的错误码判断方式快得多。如果调用深度为 1,并且错误发生的概率为 50%,则显式判断错误码测试将大获全胜。调用深度和错误概率决定了这些测试之间的差异。我要问一个简单而潜在有用的问题:一个错误要多罕见才被看作是异常情况?不幸的是,答案是这要看情况。这取决于代码、硬件、优化器、异常处理的实现,等等等等。C++ 异常的设计假设答案至少在 1:100 的范围。换句话说,错误指示的传播要远比显式的处理更为常见。

空间占用问题可能比运行期问题更难解决。对于那些遇到不能在本地处理的错误就可以立即终止的系统,我可以想象这样一个实现,在遇到 throw 时立即终止程序。但是如果要传播和处理错误,那么就不可避免,需要面对选择各种困难的折中。

对于错误处理这团乱码,任何解决方案都很可能遇到 N+1 问题(§4.2.5)[Stroustrup 2018a]。

奇怪的是,当初 C++ 引入异常时,人们担心的问题之一就是异常不够通用。许多人认为恢复(resumption)语义必不可少 [Stroustrup 1993]。当时我的猜测是,允许恢复将使异常处理的速度至少再降低两倍。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文