如何:异常安全模型 https://msdn.microsoft.com/zh-cn/library/hh279653(v=vs.110)

来源:互联网 发布:真实的恐怖事件知乎 编辑:程序博客网 时间:2024/05/19 17:48
此文章由机器翻译。 将光标移到文章的句子上,以查看原文。 更多信息。
译文
原文

如何:异常安全模型

Visual Studio 2012
其他版本

一个异常结构的优点是执行,并提供有关异常的数据时,直接从异常。该第一个捕获的语句处理它的语句跳转。 处理程序可以是任意数量的级别在调用堆栈。 调用在 try 语句和 throw 语句之间不需要任何功能了解有关引发的异常。 但是,它们必须经过专门设计,以便可以超出范围“意外”随时异常可能从下的位置传播,并且这样做,而无需忘记部分已创建的对象、泄漏的内存或在不可用状态的数据结构。

基本技术 

一个可靠的异常处理的策略需要仔细考虑,应是的一部分设计过程。 通常,大多数异常检测将引发在软件的较低层中,但是,这些层通常没有足够的上下文处理错误也不显示消息。最终用户。 在中间层,函数可以捕获并再次引发异常,则它们必须检查异常对象时,也具有不同的有用信息提供上层最终捕获异常。 函数应捕获,并“和”异常,只有 + 当可以从它完全还原。 在大多数情况下,在中间层的正确的行为是让调用堆栈的异常传播。 在最高的层,允许未经处理的异常终止程序可能适用,如果在其有效性不能保证的状态使程序处于。

无论必须基于以下基本规则设计功能处理异常,帮助确保为“异常安全的”,它。

Hh279653.collapse_all(zh-cn,VS.110).gif保持资源选件简单类

当您封装在选件类中手动资源管理,请使用执行 nothing 管理每个资源的选件类;否则,可能引入泄漏。

Hh279653.collapse_all(zh-cn,VS.110).gif使用 RAII 个 management 资源

若要是异常安全的,函数必须确保其分配了使用 malloc 或 new 销毁的对象,并且,所有资源 (如文件句柄关闭或释放,即使引发异常。 "获取资源即初始化" (raii) (RAII) 个关系管理这样的资源对于生存期自动变量。 因为异常,当函数超出范围时,通过常规返回或,所有完全构造的自动变量的析构函数调用。 一个 RAII 包装对象 (例如智能指针调用适当的删除或关闭的功能在其析构函数。 在异常安全的代码,立即将每个资源所有权更改为 RAII 对象是极其重要。请注意资源的 vectorstringmake_sharedfstream以及类似的选件类处理获取您的。但是,在中,因为资源获取由用户执行而不是对象,unique_ptr 和传统 shared_ptr 构造是特定的;因此,它们计数,因为 资源版本是损坏,但有问题的作为 RAII。

三个异常确保 

通常,异常安全讨论根据功能可以提供的三个异常确保:NO-失败确保强的保证和 基本保证

Hh279653.collapse_all(zh-cn,VS.110).gifNO-失败确保

NO-失败 (或,“NO-引发”) 以确保是函数可以提供的最严格的保证。 指出,该函数不会引发异常也不允许一传播。 但是,不能可靠提供此确保),除非您知道此函数调用的所有功能也都 NO-失败,或者 (b) 您知道引发的所有异常捕获,在其达到此功能之前或 (c) 将捕获并正确处理可能达到此函数的所有异常。

通过强保证和了基本的确保取决于所使用的假设析构函数是 NO-失败。 所有容器和输入其析构函数不引发标准库保证。 还有一个相反的要求:标准库需要为其提供有关示例的用户定义的类型,因为模板参数必须具有非引发的析构函数。

Hh279653.collapse_all(zh-cn,VS.110).gif强确保

通过强确保,表明,如果因异常,函数超出范围,它将不会泄漏内存,并程序状态将不会修改。 提供了一个强大的确保的基本功能会陷于提交或回滚语义的事务:也完全成功或它不会有任何效果。

Hh279653.collapse_all(zh-cn,VS.110).gif基本确保

这个基本确保最弱三。 但是,那么,当强确保太大开销在内存消耗或在性能时,可能是最佳选择。 这个基本确保,表明,如果发生异常,内存不会泄漏,并且对象仍在一个可用的状态,即使可能已更改了数据。

异常安全的选件类 

选件类可帮助确保自己的异常安全,即使通过不安全的功能使用,通过阻止部分构造或部分被销毁。 如果选件类构造函数完成之前退出,则对象不会创建,并且其析构函数不会调用。 尽管对异常进行初始化的自动变量将有自己的析构函数不受智能指针或类似的自动变量托管调用的,动态分配的内存或资源将泄漏。

内置类型是所有 NO-失败,并且,标准库类型以支持基本确保在最小位数。 遵循必须是异常安全的任何用户定义的类型的准则:

  • 使用智能指针或其他 RAII 类型的包装管理所有资源。 避免在您的选件类析构函数的资源管理功能,因为析构函数不调用,如果构造函数引发异常。 但是,因此,如果选件类是控件资源的专用资源管理器,然后使用析构函数管理资源是可以接受的。

  • 了解基类构造函数引发的异常在派生类构造函数不能和。 如果要将和重新在派生的构造函数的基类异常,请使用函数 try 块。 有关更多信息,请参见如何:在基类构造函数 (C++) 的异常

  • 是否考虑存储所有选件类状态在智能指针所包装的数据成员,特别是,如果选件类具有允许失败“初始化的概念”。虽然 C++ 允许使用未初始化的数据成员,则它不支持未初始化或部分初始化的选件类实例。 构造函数必须成功或失败;,如果构造函数不已完成运行,就不能创建对象。

  • 不要允许任何异常从析构函数转义。 C++ 一个基本的公理是析构函数不应允许异常传播调用堆栈。 如果析构函数必须执行可能需要异常引发的操作,则在 try-catch 必须先块和和异常。 标准库在任何析构函数为其定义的此保证。

请参见 

概念

错误和异常处理(现代C++)
如何:异常和非异常代码之间的接口
0 0
原创粉丝点击