禁用C ++异常,如何让std :: throw()立即终止?

时间:2011-08-30 20:27:27

标签: c++ exception-handling g++ exit

这个C ++程序是一个CGI脚本,我不想处理异常。我宁愿获得边际性能提升,让OS(Linux)在进程终止后进行清理。

我正在使用标准C ++库,并希望在Perl中使用任何函数die每当它抛出异常时。无需展开,或运行任何进一步的代码< / em>在我的过程中。

-fno-exceptions如何运作?如果我的代码中根本没有捕获,并且基本上假装不存在异常。但我使用可以 throw()的std :: c ++库?

5 个答案:

答案 0 :(得分:60)

选项#1:简单地永远不会捕获异常。

当他们没有被抛出或被抓住时,例外没有太大的开销;如果你正在投掷并且没有准备好赶上,那么你无论如何都要死,所以那时的表现影响是微不足道的。另请注意,如果未处理异常,则不会执行堆栈展开;程序将在不执行堆栈展开的情况下终止。

值得注意的是,在G ++中,异常几乎没有实际抛出的开销。 G ++生成足够的额外信息以通过堆栈追溯程序的执行,以及一些额外的代码来调用析构函数等 - 但是在实际抛出异常之前,不会使用这些额外的代码或数据。因此,您不应该看到启用了异常但未使用异常的代码与禁用异常的代码(通过任何机制)之间的性能差异。

选项#2:通过-fno-exceptions

此标志指示G ++ do two things

  1. 删除STL库中的所有异常处理;投掷被abort()电话
  2. 取代
  3. 删除堆栈展开数据和代码。这节省了一些代码空间,并且可能使编译器的寄存器分配更容易(但我怀疑它会对性能产生很大的影响)。但值得注意的是,如果抛出异常,并且库试图通过-fno-exceptions代码展开,它将在该点中止,因为没有展开数据。
  4. 这将有效地将所有异常转换为abort() s,如您所愿。但请注意,您将无法throw - 代码中的任何实际throwcatch都会导致编译时错误。

    选项#3 :(不可移植,不推荐!)挂钩__cxa_allocate_exception。

    使用(其中包括)__cxa_allocate_exception和__cxa_throw内部库函数来实现C ++异常。您可以实现一个LD_PRELOAD库,将这些函数挂钩到abort():

    void __cxa_allocate_exception() { abort(); }
    void __cxa_throw() { abort(); }
    

    警告:这是一个可怕的黑客攻击。它应该适用于x86和x86-64,但我强烈建议不要这样做。值得注意的是,它实际上不会像-fno-exceptions那样提高性能或节省代码空间。但是,它会允许throw 语法,同时将throw转换为abort() s。

答案 1 :(得分:18)

-fno-exceptions turns all standard library throw's into a call to std::abort()。它处理你无法直接修改的部分,其余的是在代码中根本不使用它们。

当然,我真的怀疑你这样做的理由。实际投掷时,你只会“失去”表现,并且你会丢掉一些重要且有用的语言。

答案 2 :(得分:10)

如果有人偶然发现这个问题,我想纠正@GManNickG和(https://stackoverflow.com/a/7249460/157344)和@bdonlan(https://stackoverflow.com/a/7249442/157344)在答案中所说的内容。不幸的是,关于“-fno-exception”删除所有异常处理代码并将所有抛出中止的部分都是错误的。好吧 - 部分错了。当您使用此标志编译有问题的库(libstdc ++ v3)时,这是正确的,但如果您在使用此标志编译的自己的代码中使用此库(作为.a或.so或.dll或其他),则为true 。在后一种情况下,您的代码中的异常处理代码是被禁止的,但是库内的异常处理的所有调用仍然存在(因为库已编译 WITHOUT 此标志,启用了异常),所以如果你使用new然后您的可执行文件拥有异常处理代码 - 唯一的区别是您不能使用catch()(代码中禁止)对这些异常进行任何操作,因此所有投掷都有效地结束为abort(),但这只是因为没有人抓住它们。

答案 3 :(得分:9)

引用:

这个C ++程序是一个CGI脚本,我不想处理异常。

  • 然后不要。简单。异常将很快到达堆栈顶部。

但我会敦促你这样做。这样做意味着你正在考虑可能出错的事情。

答案 4 :(得分:1)

只是不要在代码中的任何地方捕获它们。在这种情况下,将调用终止处理程序,您的程序将“崩溃”。