代码之家  ›  专栏  ›  技术社区  ›  uuu777

项目级C++异常处理策略

  •  4
  • uuu777  · 技术社区  · 17 年前

    假设我在每个级别上都有嵌套方法A、B、C、D、E,我们在正常的操作过程中返回错误,但E也可能抛出异常(例如STL插入时内存不足)。例外情况很少发生,实际退绕的速度/速度不是问题。

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

    1. 把它放在最底层,并转换为正常的错误状态。

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

    缺点:看起来不酷,增加了明显的尝试/捕捉的咔嗒声-几乎在每一次插入和推回,直到在STL容器周围写异常安全包装,有意见,有运行时性能惩罚的尝试块(有意见,没有处罚)。

    1. 把它放在上面。

    优点:看起来很酷,没有碰撞声。

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

    1. 把它作为应用程序的完全重新启动处理:把所有没有被异常处理破坏的东西都处理掉,然后重新启动。

    优点:可预测,会容忍在异常安全代码中的小瑕疵,比崩溃要好得多。

    缺点:太苛刻了

    1. 编写自定义分配程序,允许在进入调用堆栈之前检查a()的内存预留。

    void a()
    {
        ...
        x = b();
        ...
    }
    
    int b()
    {
        y = c();
    
        ...
    
        return y + d();
    }
    
    int d()
    {
        ...
        z = e();
        ...
    }
    
    3 回复  |  直到 15 年前
        1
  •  1
  •   SCFrench    15 年前

    无论您在这里做什么决定,我都鼓励您将异常安全的概念强加于(或者至少是轻敲)其他开发人员的头脑。根据我的经验,编写异常安全代码的过程导致了更干净的设计、事务性代码。

    作为一个好处,这种编码风格在不考虑异常情况的情况下都能工作,而反过来则不正确。

        2
  •  6
  •   Jack Lloyd    17 年前

    一般来说,我觉得一个系统最好是通过使用一个错误处理策略来实现的-每次在这两者之间转换时,都会有一些裂缝,这些裂缝可能会在两者之间滑动。大多数情况下,我更喜欢任何合理支持它们的语言中的异常(即,不支持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技术被认为是与异常相关的,但实际上它们在那里是完全必要的(因为你没有其他方法可以做到),在那里,使用错误代码处理技术它们是非常有用的;虽然理论上你可以自己处理所有资源释放,但实际上你可以并且将忘记一些MES。让编译器来做(tm)

    你真的需要尝试/抓住每一个操作吗?为什么不用try/catch包装整个函数并返回一个错误呢?一方面,它使人们更容易区分,比如说,阅读失败之类的错误 std::vector 索引和内存分配失败引发 std::bad_alloc .

    Try/Catch的性能损失很大程度上取决于ABI和编译器。我相信现代ABI(例如x86-64 Unix ABI)和现代GCC的成本是非零但最小的,但在其他编译器上,它是可以注意到的。如果你真的想知道,你必须在你的特定编译器/平台上运行实验。

        3
  •  0
  •   R Samuel Klatchko    17 年前

    我会根据几个因素做出决定。

    1)您的代码库有多干净。如果您的代码库相对干净,则更容易验证代码是否是异常安全的,并且您可以在顶部捕获异常。但是,如果代码是一堆乱七八糟的代码,那么将更容易捕获异常并依赖于现有的错误处理。

    2)你的团队有多好。假设您不是唯一的编码人员,那么要处理的另一个问题是您的团队成员是否都准备好编写异常安全代码。如果您的团队中有人不能打破旧习惯,那么您应该将异常降低,因为这样的程序员可能会随着时间的推移引入异常不安全的代码。