繁体   English   中英

在最简单的分配中打破严格的混叠规则

[英]Breaking the strict-aliasing rule in the simplest assignment

在阅读了理解严格的混叠文章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); 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编译器在Debug和Release版本中生成的Assembly代码(为简单起见,使用32位代码)。 在这两种情况下, f2分配都转换为2条movss指令,如下所示:

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

因此,我了解现代C ++编译器是否会在违规行上给出错误或警告。 但是,如果编译成功,哪种优化的Assembly代码会产生意外结果?

笔记:

  1. 此代码有意违反严格混叠规则。

  2. 我知道这是UB。

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

一旦有了UB,一切都会发生。

编译器可以在程序中执行任何操作。

一些编译器在检测到UB时会“删除” UB分支,因此您的程序可能不显示任何内容。 这就是为什么在UB上进行推理没有用的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM