为什么编译器不能优化 try-catch 块中的单个 throw 语句?

问题描述 投票:0回答:1

我只是在 Compiler Explorer 上玩一些 C++ 代码,并在编译简单的

try
/
catch
块时注意到一些意外的行为。以下两个片段都是使用 gcc 使用优化标志
-O3
进行编译的(现场示例)。

在第一个程序中,整个

try
/
catch
块被删除,因为行为上没有明显的差异,导致与
return 0;
相同的组件。这正是我期望编译器产生的结果。

int main() {
    try {
        int x{ 10 };
    }
    catch (...) {
    }

    return 0;
}
main:
        xor     eax, eax
        ret

在第二个片段中,我

throw
是一个异常,而不是仅仅初始化
int
。抛出该异常后,我将继续使用
catch
-all 处理程序,该处理程序是空的。之后就只有
return 0;
语句了。这意味着该程序的可观察行为将与第一个程序相同。然而,大会表明,整个
try
/
catch
仍在继续。

int main() {
    try {
        throw 10;
    }
    catch (...) {
    }

    return 0;
}
main:
        push    rcx
        mov     edi, 4
        call    __cxa_allocate_exception
        xor     edx, edx
        mov     esi, OFFSET FLAT:_ZTIi
        mov     DWORD PTR [rax], 10
        mov     rdi, rax
        call    __cxa_throw
        mov     rdi, rax
        call    __cxa_begin_catch
        call    __cxa_end_catch
        xor     eax, eax
        pop     rdx
        ret

现在我想知道为什么编译器无法识别整个

try
/
catch
块是“死代码”(或者不是?),或者如果它可以识别它,为什么它不优化它.

c++ exception error-handling try-catch compiler-optimization
1个回答
0
投票

第一个例子相当于:

int main() {
    int x{ 10 };
    return 0;
}

由于try块中的语句是安全的,编译器会检测到永远不会到达catch块,并且可以通过摆脱try catch块来进行优化。

在第二个代码片段中,您抛出了一个异常,因此 try catch 块不是死代码,因为控件将进入 catch 块,即使它是空的。

为什么不优化它?

虽然catch块中没有执行任何代码,但抛出的异常将继续运行,除非catch块显式处理并捕获该异常。因此,执行将进入 catch 块,然后从中退出,并将控制权(默默地)传递给该空块后面的代码。

© www.soinside.com 2019 - 2024. All rights reserved.