首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >你(真的)写了异常安全代码吗?

你(真的)写了异常安全代码吗?
EN

Stack Overflow用户
提问于 2009-12-05 19:48:15
回答 11查看 124.2K关注 0票数 340

异常处理(EH)似乎是目前的标准,通过搜索网页,我找不到任何新的想法或方法试图改进或取代它(嗯,有些变化,但没有什么新奇的)。

虽然大多数人似乎忽略它或仅仅接受它,EH 有一些巨大的缺点:异常在代码中是不可见的,它会创建许多很多可能的退出点。Joel在软件上写了一个关于它的文章。与goto的比较恰如其分,这让我重新思考了EH。

我尽量避免EH,只使用返回值、回调或任何符合目的的方法。但是--当您必须编写可靠的代码时,您不能忽略EH::它从new开始,这可能会引发异常,而不是只返回0(就像以前那样)。这使得任何行的C++代码都容易受到异常的攻击。然后C++基础代码中更多的地方会抛出异常..。std做这个,依此类推。

这感觉就像在摇摇欲坠的地面上行走,..。所以,现在我们不得不处理例外情况!

但这很难,真的很难。您必须学会编写异常安全代码,即使您有一些使用它的经验,它仍然需要反复检查任何一行代码才是安全的!或者您开始在任何地方放置try/catch块,这会使代码变得杂乱无章,直到它达到不可读状态。

EH取代了旧的干净的确定性方法(返回值.),该方法只有少数但可以理解和容易解决的缺点,它可以在代码中创建许多可能的退出点,如果您开始编写捕获异常的代码(在某个时候被迫执行的操作),那么它甚至会在代码中创建多种路径( catch块中的代码,考虑需要记录程序而不是std::cerr .)的服务器程序。呃有优势,但这不是重点。

我的实际问题:

  • 您真的编写异常安全代码吗?
  • 你确定你最后的“生产准备”代码是异常安全的吗?
  • 你能确定吗,确实如此?
  • 你知道和/或实际使用其他可行的方法吗?
EN

回答 11

Stack Overflow用户

发布于 2009-12-05 20:37:14

在C++中编写异常安全代码与其说是使用大量的try {} catch {}块,不如说是使用大量try{}catch{}块。它是关于记录您的代码提供了什么样的保证。

我推荐阅读Herb的本周大师系列,特别是第59、60和61期。

总之,您可以提供三个级别的异常安全:

  • Basic:当代码抛出异常时,您的代码不会泄漏资源,并且对象仍然是可销毁的。
  • 强:当代码抛出异常时,它将保持应用程序的状态不变。
  • 不抛出:您的代码从不抛出异常。

就我个人而言,我发现这些文章很晚,所以我的许多C++代码绝对不是例外安全的。

票数 33
EN

Stack Overflow用户

发布于 2009-12-05 20:03:25

我们中的一些人使用例外已经有20多年了。举个例子,PL/I有。在我看来,它们是一种新的、危险的技术的前提似乎是值得怀疑的。

票数 21
EN

Stack Overflow用户

发布于 2009-12-05 21:00:37

首先(正如Neil所说),SEH是微软的结构化异常处理。它与C++中的异常处理类似但不完全相同。实际上,如果您想在Visual中使用它,就必须使用启用C++异常处理 --默认行为并不能保证本地对象在所有情况下都被销毁!在这两种情况下,异常处理并不是很难--只是不同而已。

现在来问你的实际问题。

您真的编写异常安全代码吗?

是。在所有情况下,我都为异常安全代码而奋斗。我使用RAII技术来传播对资源的范围访问(例如,boost::shared_ptr用于内存,boost::lock_guard用于锁定)。通常,雷伊范围防护技术的一致使用将使异常安全代码的编写更加容易。诀窍是学习什么是存在的以及如何应用它。

你确定你最后的“生产准备”代码是异常安全的吗?

不是的。它和它一样安全。我可以说,在几年的24/7活动中,我没有看到由于异常而导致的进程故障。我不期望完美的代码,只是写得很好的代码。除了提供异常安全之外,上述技术还以一种几乎不可能用try/catch块实现的方式来保证正确性。如果您正在捕获顶级控件范围(线程、进程等)中的所有内容,那么您可以确保在遇到异常(大部分时间)时将继续运行。同样的技术还将帮助您在遇到异常时继续正确运行,不带、、、处处阻塞

你能确定是真的吗?

是。您可以通过彻底的代码审核来确定,但是没有人真的这样做,是吗?然而,常规的代码评审和谨慎的开发人员在实现目标方面有很长的路要走。

你知道和/或实际使用其他可行的方法吗?

多年来,我尝试过一些不同的方法,比如在上层位编码状态(ala S)或可怕的setjmp() ... longjmp()攻击。这两种情况在实践中都是完全不同的。

最后,如果您养成了应用几种技术的习惯,并仔细考虑了在什么地方可以对异常进行实际操作,那么最终您将得到非常可读的代码,这些代码是异常安全的。您可以通过以下规则来总结这一点:

  • 您只希望看到try/catch时,您可以对特定的异常做些什么。
  • 您几乎不希望看到代码中的原始newdelete
  • 一般避免使用std::sprintfsnprintf和数组--使用std::ostringstream格式化并用std::vectorstd::string替换数组
  • 当有疑问时,在滚动自己的功能之前,在Boost或STL中查找功能。

我只能建议您学习如何正确地使用异常,如果您计划用C++编写结果代码,则应该忘记结果代码。如果要避免异常,可以考虑使用另一种语言编写没有他们使他们安全。如果您想真正学习如何充分利用C++,请阅读草本萨特尼古拉·乔苏蒂斯斯科特·迈尔斯的几本书。

票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1853243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档