c++ - 项目级c++异常处理策略

标签 c++ exception-handling

假设我在每个级别上都有嵌套方法 a、b、c、d、e,我们在正常操作过程中返回错误,但 e 也可能抛出异常(例如,STL 插入时内存不足)。异常(exception)情况非常少,实际平仓发生的速度有多快/多慢不是问题。

在这种情况下,最合适的异常处理策略是什么?

  1. 将其置于最低级别并转换为正常错误状态。

优点:不需要编写异常安全代码,最容易实现,最容易测试,最容易理解,展开所需的编译时间信息最少。

缺点:看起来不太酷,添加了明显的 try/catch 杂音 - 实际上围绕每个插入和 push_back,直到围绕 STL 容器编写异常安全包装器的程度,有人认为 try block 会影响运行时性能(也有意见认为完全没有惩罚)。

  1. 在顶部处理它。

优点:看起来很酷,没有杂音。

缺点:真的很难直观地验证中间的所有代码确实是异常安全的,以测试所有异常展开路径将是

  1. 将其处理为应用程序的完全重启:清除所有未被异常处理清除的内容并重新启动

优点:可预测,可以容忍异常安全代码中的小缺陷,比崩溃要好得多。

缺点:太苛刻了

  1. 编写自定义分配器,允许在深入调用堆栈之前检查 a() 处的内存保留。

void a()
{
    ...
    x = b();
    ...
}

int b()
{
    y = c();

    ...

    return y + d();
}

int d()
{
    ...
    z = e();
    ...
}

最佳答案

一般来说,我觉得一个系统最好在整个过程中使用单一的错误处理策略 - 每次您在两者之间转换时,都会有一些裂缝可以在两者之间滑动。大多数时候我更喜欢任何合理支持它们的语言的异常(即,不是在 C 中——该死的 setjmp/longjmp)。鉴于您描述的设计,您的系统的大部分已经使用错误代码,将异常转换为 e 中的错误代码并假装系统中不存在异常似乎是有意义的。

另一方面,您确定只有 e 可以抛出异常吗?在 C++ 中很容易从您通常不会想到的地方抛出异常 - 调用 new,几乎任何标准库的使用,等等。

请注意异常安全,使用像 RIAA 这样的技术,在你有像这样的代码时也很有用

int* workspace[] = new int[500];
...
if(some_function() == ERROR)
  return SOME_FUNCTION_FAILED; // oops just leaked memory
...
delete[] workspace;

(或任何其他获取资源的东西)

RIAA 技术被认为与异常有关,但实际上它们在那里是完全必要的(因为您别无选择),而对于错误代码处理技术,它们非常有用;虽然理论上您可以自己处理所有资源释放,但实际上您有时会忘记。让编译器来做(tm)

您真的需要尝试/捕获每个操作吗?为什么不将整个函数包装在 try/catch 中并返回错误。一方面,它更容易区分读取错误的 std::vector 索引等失败和抛出 std::bad_alloc 的内存分配失败。

try/catch 的性能损失在很大程度上取决于 ABI 和编译器。我相信在带有现代 GCC 的现代 ABI(例如 x86-64 Unix ABI)上,成本不为零但很小,但在其他编译器上它可能很明显。如果你真的想知道,你必须在你的特定编译器/平台上运行实验。

关于c++ - 项目级c++异常处理策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1610668/

相关文章:

c++ - glScaled(size/window_size) 不正确的图像

c++ - 使用反向迭代器的中点

c# - 在 C# 中使用 DLL

c++ - 通过函数内部的指针删除

c++ - 析构函数 C++ 中的异常

java - 具有未检查异常与已检查异常的接口(interface)声明

Java try-finally 竞争条件?

c++ - Cassandra 中协调器节点和 C++ 驱动程序的联系点之间的区别?

.net - 构造函数链和空引用测试

c++ - 在 C++ 中通过指针捕获异常