草庐IT

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

coder 2024-02-17 原文

假设我在每个级别上都有嵌套方法 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++ - 项目级c++异常处理策略的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  5. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  6. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  7. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  8. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  9. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐