为什么编译器没有完全优化异常?[复制]

Why does the compiler not completely optimize away the exception? [duplicate]

提问人:user5406764 提问时间:9/24/2023 更新时间:9/24/2023 访问量:57

问:

这个程序应该总是返回 0(除非我遗漏了什么):

int main()
{
    try {
        throw;
    } catch (...) { 
        return 0; 
    }
}

那么,为什么整个异常没有得到优化呢?

带有 gcc 13.2 -std=c++23 -O3 的 Gotbolt 组件

main:
        push    rcx
        call    __cxa_rethrow
        mov     rdi, rax
        call    __cxa_begin_catch
        call    __cxa_end_catch
        xor     eax, eax
        pop     rdx
        ret
C++ 异常 优化

评论

2赞 Ted Lyngmo 9/24/2023
你知道你正在尝试重新抛出一个不存在的异常,对吧?“只有在当前正在处理异常时才允许使用这种形式(如果以其他方式使用,它会调用 std::terminate)” - 如果你真的这样做并不重要 - 编译器仍然将代码留在那里。throw;throw 0;
4赞 Alan Birtles 9/24/2023
可能是因为没有人费心去优化这样一个荒谬的案例。每一次优化都会使编译器变得更加复杂,可能更慢,是潜在错误的根源,并且需要开发人员时间来实现,因此编译器开发人员会选择优化常见情况,在实际代码中不太可能发生的晦涩情况可能不会实现

答:

1赞 user17732522 9/24/2023 #1

这个程序应该总是返回 0(除非我遗漏了什么):

否,不会引发新的异常。 没有操作数会重新引发当前处理的异常。如果不存在此类异常,则将导致调用终止程序。throw;throwstd::terminate

因此,您的程序应该通过调用 来终止,而不是通常以退出代码退出。std::terminate0


假设这不是函数,而是函数。mainnotmain

那么你可能会在某个地方这样做:

try { throw 0; }
catch(...) { notmain(); }

这需要是一个noop,在语句之后继续执行。

也有可能调用某个位置,而不是由处理程序包围。在这种情况下,您正在尝试在没有异常处于活动状态的情况下重新抛出,因此需要调用。notmain()catchstd::terminate

因此,编译器必须具有一些逻辑,以检查是否正在处理异常并采取相应的行动,这就是您在程序集中看到的这些函数调用背后的实现。notmain

现在,如果函数是,您不可能处理任何异常,因此程序必须始终以调用终止,编译器可以对此进行优化,但这是一个非常具体且无用的情况,不太可能与实现优化相关。::mainstd::terminate