16

C++ 的假定精神是“你用什么,你付多少”。但是,由于异常及其在 STL 中的广泛使用,这可能会让人非常沮丧。

在任何人说“打开异常”之前,生活对我们必须生活的编程环境并不那么慷慨。我的是内核编程,其中执行环境没有提供足够的 C++ 运行时来展开堆栈等。

当 STL 容器无法为其底层后备存储重新分配存储时,它们将抛出分配失败异常。当环境中未启用异常时,程序将相当神秘地崩溃:我已经看到实现直接中止,或者只是假设分配有效,即使它没有。

我遇到的许多 C ADT 库通过返回错误代码或将错误作为输出参数来预先处理此问题。

处理这个问题的“最佳”C++ 方法是什么?

澄清

我不想使用标准库,我不能。我不是在问“我怎么做不能做的事”。我在问:“给定一个干净的石板,容器库应该如何构建。”

4

2 回答 2

18

这很简单:不要再相信你应该对所有事情都使用标准库。

标准库旨在成为您使用功能的默认位置。但是,这并不意味着它适用于所有情况。比如内核编程,例如。这是一个相当小众的环境,您需要直接和明确地控制大多数 C++ 程序员不关心的事情。

发出失败信号的 C++ 标准机制,尤其是从容器分配内部内存之类的东西,是抛出异常。绝大多数应用程序都不会费心去捕捉那个异常;万一他们内存不足,他们就会死去。这对他们来说很好。在这些情况下返回错误代码充其量是困难的(考虑重新分配 a std::vector<std::string>。如果内部std::strings 中的一个得到 OOM 会发生什么?谁得到错误代码?你甚至如何表示构造函数失败,因为std::string复制构造函数抛出异常?)。只有真正需要关心的人才会足够关心才能抓住它。

您在受限环境中工作,这是标准库无法处理的环境。所以......不要在那种环境中使用它。

我的建议是追踪一份 EASTL 的副本。它真的是为这种事情而设计的。我链接到的 Github 存储库有一些错误修复等,但它仍然基本相同。这不是一个糟糕的代码。它们的类 STL 容器提供了大部分接口,因此它们大多可以直接替代。但是它们提供了特殊的功能来专门控制内存分配。而且他们不投掷(或者至少,你可以关闭投掷)。

于 2012-03-25T04:35:49.250 回答
3

看来问题确实是您的环境。堆栈展开并不是非常复杂。我明白你为什么要对它施加一些限制——抛出一个 10 MB 的对象是合法的 C++——但即使在内核模式下,你也应该能够支持std::bad_alloc通过非虚拟调用进行抛出。

考虑到这一点,STL 设计非常合理。该接口只需要最少的异常支持,并且可以根据环境定制实现。

于 2012-03-26T10:01:00.250 回答