[英]Feature, bug or UB? The expected infinite loop in my code is deleted when using gcc -O2
代码如下:
#include <cstdint>
#include <iostream>
using u64 = std::uint64_t;
u64 *test() {
u64 *a, *p;
p = (u64 *)&a;
a = (u64 *)&p;
{
for (int i = 0; i < 100; ++i) {
p = new u64((u64)p);
}
}
while (true) {
if ((u64)p == 0) {
break;
}
p = (u64 *)*p;
}
return p;
}
int main() {
std::cout << test() << std::endl;
}
function测试编译的asm如下:
test():
xor eax, eax
ret
你可以看到https://godbolt.org/z/8eTd8WMzG 。
事实上,当最终的 stmt 是return a;
尽管编译器会发出有关重新调整本地地址的警告。 如果我将a
和p
设为全局变量,一切正常,请参阅https://godbolt.org/z/n7YWzGvd5 。
所以,我想我可能会面对一些 ubs,以至于它的行为不符合我的预期?
请帮我, :)
指令p = (u64 *)&a;
和a = (u64 *)&p;
紧随其后的赋值和取消引用变量会破坏严格的别名规则,从而导致未定义的行为。 实际上, p
和a
属于u64*
类型,而&a
和&p
属于u64**
类型。 此外, p = (u64 *)*p;
是违反严格别名规则的指令的完美示例: u64**
、 u64*
和u64
是三种截然不同的不同类型。
如果要解决这个问题,首先需要检查大小和类型的 alignment 是否匹配(在主流 64 位架构上应该没问题)。 此外,您应该使用std::bit_cast
或memcpy
来执行转换(请参阅此相关帖子)。
此外,请注意,没有副作用的无限循环也是未定义的行为。 由于在您的情况下p
不能是 null 。 检测到您的循环是无限的并且没有任何副作用的编译器可以将其删除(或者也可以生成错误的代码)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.