gpt4 book ai didi

具有未定义结果的 C 代码,编译器生成无效代码(使用 -O3)

转载 作者:太空狗 更新时间:2023-10-29 17:07:40 26 4
gpt4 key购买 nike

我知道当你在 C 程序中做某些事情时,结果是不确定的。但是,编译器不应该生成无效(机器)代码,对吧?如果代码做了错误的事情,或者如果代码生成了段错误或其他东西,这将是合理的......

这是根据编译器规范应该发生的,还是编译器中的错误?

这是我正在使用的(简单的)程序:

int main() {
char *ptr = 0;
*(ptr) = 0;
}

我正在使用 -O3 进行编译。那不应该生成无效的硬件指令,对吧?使用 -O0,我在运行代码时遇到段错误。这看起来理智多了。

编辑:它正在生成一条 ud2 指令...

最佳答案

ud2指令是“有效指令”,它代表未定义指令并生成无效操作码异常clang显然 gcc当程序调用未定义的行为时可以生成此代码。

根据上面的 clang 链接,解释如下:

Stores to null and calls through null pointers are turned into a __builtin_trap() call (which turns into a trapping instruction like "ud2" on x86). These happen all of the time in optimized code (as the result of other transformations like inlining and constant propagation) and we used to just delete the blocks that contained them because they were "obviously unreachable".

While (from a pedantic language lawyer standpoint) this is strictly true, we quickly learned that people do occasionally dereference null pointers, and having the code execution just fall into the top of the next function makes it very difficult to understand the problem. From the performance angle, the most important aspect of exposing these is to squash downstream code. Because of this, clang turns these into a runtime trap: if one of these is actually dynamically reached, the program stops immediately and can be debugged. The drawback of doing this is that we slightly bloat code by having these operations and having the conditions that control their predicates.

归根结底,一旦您调用了未定义的行为,您的程序的行为就无法预测了。这里的理念是,与产生一个看似可以工作但实际上已损坏的程序相比,硬性崩溃并向开发人员指示出现严重错误并允许他们从正确的点进行调试可能更好。

正如 Ruslan 指出的那样,它是“有效的”,因为它保证引发无效的操作码异常,而不是其他可能在未来变得有效的未使用序列。

关于具有未定义结果的 C 代码,编译器生成无效代码(使用 -O3),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26309300/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com