是否允许编译器优化异常引发
Are compilers allowed to optimize-out exception throws?
我们今天一直在讨论这个话题,我们谁都无法对这个问题提出明确的答案。请考虑以下情况:
int foo()
{
int err;
err = some_call(1);
if (err != 0)
return err;
err = some_call(2);
if (err != 0)
return err;
err = some_call(3);
if (err != 0)
return err;
err = some_call(4);
if (err != 0)
return err;
bar();
return err;
}
有很多代码重复。显然,这可以用宏分解,可惜不是用模板(因为返回条款)。或者至少不是直接的。
现在的问题是,如果我们要用异常替换这些返回错误代码,并立即捕获这些异常,编译器是否允许并且足够智能来检测模式并完全避免抛出异常?
以下是我的意思的例证:
int foo()
{
try
{
// some_call now throws a ErrorReturned exception that contains the error code upon failure.
some_call(1);
some_call(2);
some_call(3);
some_call(4);
}
catch (ErrorReturned& ex)
{
return ex.error_code();
}
bar();
return 0;
}
现在,当前没有性能问题,所以是的,我们不需要优化甚至关心它。这更多的是为了理解编译器可以做什么。
简而言之,这是一种"好"的做法吗,如果是这样,编译器可以通过根本不抛出异常来优化它吗?(假设异常构造没有副作用)
编译器是否足够聪明"似乎暗示异常在您的项目中没有用途,如果是这种情况,您首先不应该使用它们(当然,除非您实际上有可能获得异常)。
简答:不,编译器不会根据您使用的模式删除异常/异常处理。
使用 try/catch 时,它处理的异常将添加到主异常表中;可以监视、挂钩、添加和删除此表。仅仅因为您立即捕获异常并不意味着其他事情也不会发生。
侧面来源:
一篇关于Optimizing Away C++ Exception Handling
的论文概述了与异常相关的所有(几乎所有)当前优化实现。在整个过程中,它表明当前它们不是在编译时被剥离的,而是对它们进行了优化。本文本身建议对EH(异常处理)进行增强,以消除不必要的异常,总的来说,这是一本相当不错的读物。
更新(其他来源)
进一步研究该主题,GCC 编译器似乎没有优化异常;但是,它确实提供了一个选项:-fno-exceptions
。此选项将删除所有异常,并直接将其替换为abort()
调用。
另一个来源(在StackOverflow上)没有直接提到"删除异常",但确实概述了对异常所做的两个优化,setjmp/longjmp
和零成本。可以通过突出显示实际增强功能而不提及"完全删除异常"来推断没有这样的优化(至少对于提到的编译器)。可以在此处找到有关这些优化的更多详细信息的另一个来源。
- 空基优化子对象的地址
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 关闭||运算符优化
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 返回值优化:显式移动还是隐式
- 为什么异常不退出程序?
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 启用优化时的堆栈指针比较异常
- 是否允许编译器优化异常引发
- 异常、移动语义和优化:任由编译器摆布 (MSVC2010)?