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

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

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

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

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

我正在编译-O3 。 那应该不会产生无效的硬件指令,对吧? 使用-O0 ,当我运行代码时,会出现段错误。 这似乎更理智了。

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


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

从上面的clang link链接中,理由解释如下:

存储为空,并通过空指针调用变为__builtin_trap()调用(这会变成陷阱指令,如x86上的“ud2”)。 这些都会在优化代码中发生(因为其他转换如内联和常量传播的结果),我们过去只是删除包含它们的块,因为它们“显然无法访问”。

虽然(从迂腐的语言律师的角度来看)这是严格正确的, 但我们很快就了解到人们偶尔会提取空指针,并且让代码执行陷入下一个函数的顶部,这使得很难理解问题 。 从性能角度来看,暴露这些最重要的方面是压缩下游代码。 因此,clang将它们转换为运行时陷阱: 如果其中一个实际上是动态到达的,程序立即停止并且可以进行调试 。 这样做的缺点是我们通过执行这些操作并具有控制其谓词的条件来使代码略微膨胀。

在一天结束时,一旦你调用未定义的行为,你的程序的行为是不可预知的。 这里的哲学是,可能会更好地崩溃,并给开发人员一个迹象表明某些东西是严重错误的,并允许他们从正确的角度去调试,而不是产生一个似乎可行但实际上已被破坏的程序。

正如Ruslan所指出的那样,它是“有效的”,因为它保证提高一个无效的操作码异常,而不是其他未来可能有效的未使用的序列。

链接地址: http://www.djcxy.com/p/43887.html

上一篇: C code with undefined results, compiler generates invalid code (with

下一篇: I have segfaults!