gpt4 book ai didi

c++ - 在最简单的赋值中打破严格的别名规则

转载 作者:行者123 更新时间:2023-11-28 01:27:19 26 4
gpt4 key购买 nike

阅读了解严格别名一文后 https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html我明白了,违反严格的别名规则会如何导致优化构建中的意外结果。例如:

void test(int* ptr1, float* ptr2);

由于 ptr1ptr2 不兼容,编译器假定它们永远不会指向相同的内存。这允许优化代码,如果指针具有相同的值,这可能会产生意想不到的结果。

然而,在遗留代码中,严格别名规则大多在简单的赋值中被打破,比如 int n = 0; float f = *((float*)&n); 考虑以下代码:

#include <iostream>

static_assert (sizeof(float) == sizeof(int), "error");

int main(int argc, char *argv[])
{
float f1, f2;
int n = static_cast<int>(argv[1][0] - '0'); // Command argument is "0", so n = 0

memcpy(&f1, &n, sizeof(f1)); // strict-aliasing rule is not broken
f2 = *(reinterpret_cast<float*>(&n)); // strict-aliasing rule is broken

std::cout << f1 << " " << f2 << std::endl; // prints 0 0
return 0;
}

我想知道,C++ 编译器怎么可能生成优化代码,它可以给出不同的 f1f2 值,这意味着,给出意想不到的结果违反严格别名规则的代码。

我调查了 VC++ 2015 编译器在调试和发布版本中生成的汇编代码(为简单起见,使用 32 位代码)。在这两种情况下,f2 赋值都被转换为 2 个 movss 指令,如下所示:

movss       xmm0,dword ptr [n]  
movss dword ptr [esp+4],xmm0

因此,我了解现代 C++ 编译器是否会在有问题的行上给出错误或警告。但是如果编译成功,什么优化的汇编代码可以给出意想不到的结果?

注意事项:

  1. 这段代码故意违反了严格的别名规则。

  2. 我知道这是UB。

  3. 我不问什么是严格别名规则,我想知道在这种特定情况下违反规则如何导致 UB。

最佳答案

一旦拥有 UB,一切皆有可能。

编译器可以在你的程序中做任何事情。

一些编译器在检测到 UB 时“删除”UB 分支,因此您的程序可能什么都不显示。这就是为什么在 UB 上推理是无用的。

关于c++ - 在最简单的赋值中打破严格的别名规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53187292/

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