当控制达到 __builtin_unreachable 时会发生什么?

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

我写了这段代码:

enum Color
{
    kRed,
    kGreen,
    kBlue,
    kUnexistingColor
};

const char* foo(Color color)
{
    switch (color)
    {
        case kRed:
            return "red";
        case kGreen:
            return "green";
        case kBlue:
            return "blue";
        case kUnexistingColor:
        default:
            __builtin_unreachable();

    }
    return "";
}

如果我使用无效值调用

foo
,我的程序就会默默终止,或者在其他情况下返回
"blue"
。如果控制达到
__builtin_unreachable();
的程度,到底会发生什么? Windows 上是否会出现一些错误消息框,或者什么?

c++ undefined-behavior unreachable-code
2个回答
4
投票

您告诉编译器该代码无法访问。如果你违背了这个承诺,你可能会遇到未定义的行为。这已记录在here

如果控制流到达

__builtin_unreachable
点,则程序未定义。

如果你想要有明确的行为,请使用其他东西。通常将仅调试断言放在这些位置,以便您可以在运行调试版本时检测到它们。

另一种常见的方法是抛出异常。当您看到此时引发的未处理异常的故障转储时,您可以推断出已达到假定的“无法访问”代码。

您还可以将消息写入日志文件。或者,您可以默默地返回一个“错误”值,并通过不采取任何操作来干净地处理该值。

所有这一切完全取决于您了解它的重要性以及它对您的程序的持续运行有多重要。


2
投票

未定义的行为对于进行优化很有用,因为编译器假设导致未定义行为的情况不会发生。

__builtin_unreachable()
的特定位置可能对此有所帮助。


优化编译器的一个可能结果是使用基于

switch
作为索引的数组查找来替换
color
。考虑到它会生成无分支代码,这将是非常好的优化。

现在,如果没有

__builtin_unreachable()
,编译器仍然必须检查索引边界,并产生条件跳转。使用
__builtin_unreachable()
可以跳过此操作。然后,如果您传递意外的值,该函数将给出垃圾字符串,这可能会毁掉您的程序,很可能是因为它太长,或者它也可能在
\0
终止符之前具有无法访问的内存,或者它可以到达无法访问的内存立即。


如果您有能力切换到 C++23,请考虑使用

std::unreachable()
作为可移植的等效项。


如果您不希望 UB 出现在意外的代码分支上,请考虑使用

abort()
,而不是异常。这将使某些代码部分保持无异常,这可能有助于优化,而且如果您确实不排除某些情况,那么可能尝试处理它,即使有一些书面的异常处理,也可能会进一步出错。

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