当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《项目级c++异常处理策略》经验,为你挑选了1个好方法。

假设我在每个级别上嵌套方法a,b,c,d,e我们在正常操作过程中返回错误,但是e也可能抛出异常(例如STL插入时的内存不足).例外非常少,实际展开的速度和速度有多快不是问题.

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

    将其置于最低级别并转换为正常错误条件.

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

缺点:看起来并不酷,添加明显的try/catch哒 - 实际上围绕每个insert和push_back,直到在STL容器周围编写异常安全包装的程度,有观点认为try块有运行时性能损失(并且是没有任何惩罚的意见).

    把它放在顶部.

优点:看起来很酷,没有咔嗒声.

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

    将应用程序完全重新启动时将其处理为最顶层:删除未被异常处理破坏的所有内容并重新启动

优点:可预测,将容忍异常安全代码中的轻微瑕疵,比崩溃更好.

缺点:方式过于苛刻

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


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

int b()
{
    y = c();

    ...

    return y + d();
}

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

Jack Lloyd.. 6

一般来说,我认为系统最好通过使用单一的错误处理策略 - 每当你在两者之间转换时,就会出现裂缝.大多数时候,我更喜欢任何合理支持它们的语言中的异常(即,不在C语言中 - setjmp/longjmp被诅咒).鉴于您所描述的设计,您的大多数系统已经使用了错误代码,将异常转换为错误代码e并假装系统中不存在异常似乎是有意义的.

另一方面,你确定只能e抛出异常吗?在C++中,从一个你通常不会想到的地方抛出异常相当容易 - 调用new,几乎任何标准库的使用,等等.

请注意,使用像RIA​​A这样的技术时,异常安全性在您拥有类似代码时也很有用

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)成本非零但很小,但在其他编译器上它可以引人注目.如果您真的想知道,则必须在特定的编译器/平台上运行实验.



1> Jack Lloyd..:

一般来说,我认为系统最好通过使用单一的错误处理策略 - 每当你在两者之间转换时,就会出现裂缝.大多数时候,我更喜欢任何合理支持它们的语言中的异常(即,不在C语言中 - setjmp/longjmp被诅咒).鉴于您所描述的设计,您的大多数系统已经使用了错误代码,将异常转换为错误代码e并假装系统中不存在异常似乎是有意义的.

另一方面,你确定只能e抛出异常吗?在C++中,从一个你通常不会想到的地方抛出异常相当容易 - 调用new,几乎任何标准库的使用,等等.

请注意,使用像RIA​​A这样的技术时,异常安全性在您拥有类似代码时也很有用

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)成本非零但很小,但在其他编译器上它可以引人注目.如果您真的想知道,则必须在特定的编译器/平台上运行实验.

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有