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

发布于 2024-12-02 07:45:30 字数 322 浏览 3 评论 0原文

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

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

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

This C++ program is a CGI script, I have no desire to deal with exceptions. I'd rather get a marginal performance boost and let the OS (Linux) handle cleanup after the process dies.

I am using the Standard C++ Library, and want any function to die like in Perl: Whenever it throws an exception. Without unwinding, or running any further code in my process.

How does -fno-exceptions work? If I have no catch at all in my code, and basically pretend like exceptions do no exist. but I do use std:: c++ library which can throw()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

谢绝鈎搭 2024-12-09 07:45:30

选项#1:根本不捕获异常。

当异常不被抛出或捕获时,它们不会有太多开销;如果你正在扔东西并且不准备接住,那么无论如何你都会死,所以此时对性能的影响是微不足道的。另请注意,如果未处理异常,则不会执行堆栈展开;程序将直接终止,而不执行堆栈展开。

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

选项#2:传递-fno-exceptions

该标志指示 G++ 做两件事

  1. 删除 STL 库中的所有异常处理;抛出被替换为 abort() 调用 堆栈
  2. 展开数据并删除代码。这节省了一些代码空间,并且可能使编译器的寄存器分配稍微容易一些(但我怀疑它会对性能产生很大影响)。但值得注意的是,如果抛出异常,并且库尝试通过 -fno-exceptions 代码展开,它将在此时中止,因为没有展开数据。

这将有效地将所有异常转换为 abort(),如您所愿。但请注意,您将不被允许抛出 - 代码中任何实际的抛出catch都将导致编译 -时间错误。

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

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

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

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

Option #1: Simply never catch exceptions.

Exceptions don't have much overhead when they're not thrown or caught; if you're throwing and not prepared to catch, well, you're doing to die anyway, so the performance impact at that point is trivial. Note also that stack unwinding will not be performed if an exception is not handled; the program will simply terminate without performing stack unwinding.

It's important to note that, in G++, exceptions have almost no overhead when not actually thrown. G++ generates extra information sufficient to trace back the execution of the program through the stack, and some extra code to invoke destructors, etc - however none of this extra code or data is ever used until an exception is actually thrown. So you should not see a performance difference between code with exceptions enabled but not used and code with exceptions disabled (through whatever mechanism).

Option #2: Pass -fno-exceptions.

This flag instructs G++ to do two things:

  1. All exception handling in STL libraries are removed; throws are replaced with abort() calls
  2. Stack unwind data and code is removed. This saves some code space, and may make register allocation marginally easier for the compiler (but I doubt it'll have much performance impact). Notably, however, if an exception is thrown, and the library tries to unwind through -fno-exceptions code, it will abort at that point, as there is no unwind data.

This will, effectively, turn all exceptions into abort()s, as you would like. Note, however, that you will not be allowed to throw - any actual throws or catchs in your code will result in a compile-time error.

Option #3: (Nonportable and not recommended!) Hook __cxa_allocate_exception.

C++ exceptions are implemented using (among others) the __cxa_allocate_exception and __cxa_throw internal library functions. You can implement a LD_PRELOAD library that hooks these functions to abort():

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

WARNING: This is a horrible hack. It should work on x86 and x86-64, but I strongly recommend against this. Notably, it won't actually improve performance or save code space, as -fno-exceptions might. However, it will allow the throw syntax, while turning throws into abort()s.

没︽人懂的悲伤 2024-12-09 07:45:30

-fno-exceptions 将所有标准库的 throw 转换为对 std 的调用::abort()。这处理了您无法直接修改的部分,剩下的就是在代码中根本不使用它们。

当然,我真的很怀疑你这样做的合理性。当你真正抛出时,你只会“失去”性能,并且你抛出了语言中重要且有用的部分。

-fno-exceptions turns all standard library throw's into a call to std::abort(). That handles the part you can't modify directly, the rest is to not use them at all in your code.

Of course, I really doubt your justification in doing this. You only "lose" performance when you actually throw, and you're throwing out a significant and helpful bit of the language.

暖树树初阳… 2024-12-09 07:45:30

如果有人偶然发现这个问题,我想纠正 @GManNickG 和 (https://stackoverflow.com/a/7249460 /157344)和@bdonlan(https://stackoverflow.com/a/7249442/157344)在他们的答案中说。不幸的是,关于“-fno-exception”删除所有异常处理代码并将所有抛出转变为中止的部分是错误的。嗯——部分错误。当您使用此标志编译有问题的库 (libstdc++v3) 时,这是正确的,但如果您在使用此标志编译的自己的代码中使用此库(作为 .a 或 .so 或 .dll 或其他),则不是这样。在后一种情况下,您的代码中的异常处理代码被禁止,但对库内异常处理的所有调用仍然保留(因为该库是在启用异常的情况下编译的没有),所以如果您使用 new 那么你的可执行文件将会有异常处理代码 - 唯一的区别是你不能使用 catch() 来处理这些异常(这在你的代码中是被禁止的),所以所有的抛出实际上都会结束为 abort(),但只是因为没有人捕获它们。

In case anyone stumbles upon this question, I'd like to correct what @GManNickG and (https://stackoverflow.com/a/7249460/157344) and @bdonlan (https://stackoverflow.com/a/7249442/157344) said in their answers. Unfortunately the part about "-fno-exception" removing all exception handling code and turning all throws into aborts is wrong. Well - partially wrong. This is true when you compile the library in question (libstdc++v3) with this flag, but not true if you use this library (as an .a or .so or .dll or whatever) in your own code compiled with this flag. In the latter case the exception handling code in YOUR code is forbidden, but all the calls to exception handling inside the library remain (because the library was compiled WITHOUT this flag, with exceptions enabled), so if you use new then your executable WILL have exception handling code - the only difference is that you cannot anything about these exceptions with a catch() (which is forbidden in your code), so all throws effectively end up as abort(), but only because no one catches them.

猥琐帝 2024-12-09 07:45:30

Quote:

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

  • 那就不要了。简单的。异常将很快到达堆栈顶部。

但我强烈建议你这样做。这样做意味着您正在考虑可能出错的事情。

Quote:

This C++ program is a CGI script, I have no desire to deal with exceptions.

  • Then don't. Simple. The exception will get to the top of the stack very quickly.

But I would urge you to do so. To do so means that you are thinking of the things that can go wrong.

探春 2024-12-09 07:45:30

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

Just don't catch them anywhere in your code. In that case, a termination handler will be called and your program will "crash".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文