违反严格混叠,即使没有任何铸造? [英] Violating strict-aliasing, even without any casting?

查看:192
本文介绍了违反严格混叠,即使没有任何铸造?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我真的问:是别名传递?如果编译器知道A可能是B的别名,而B可能是C的别名,那么它应该记住A可能因此别名为C.也许这个明显的传递逻辑不是必需的?



这是一个例子,为了清楚起见。对我来说最有趣的例子是严格别名问题:

  // g ++ -fstrict-aliasing -std = c ++ 11 -O2 
#include< iostream>

union
{
int i;
short s;
} u;
int * i =& u.i;

int main()
{

u.i = 1; // line 1
* i + = 1; // line 2

short& s = u.s;
s + = 100; // line 3

std :: cout
<< * i \t< * i < std :: endl // prints 2
<< u.i\t< ui < std :: endl // prints 101
;

return 0;
}

g ++ 5.3.0,在x86_64(但不是clang 3.5.0)上面的输出,其中 * i ui 给出不同的数字。但它们应该给出完全相同的数字,因为 i 定义在 int * i =& ui; code> i 不会改变。



我有一个理论:当'预测' ui ,编译器会询问哪些行可能会影响 ui 的内容。其中包括第1行。和第2行,因为 int * 可以将联合成员的 int 别名。和第3行,因为任何可以影响一个联合成员( u.s )可以影响同一个联合的另一个成员。但是当预测 * i 时没有意识到第3行可以影响 int 左值

这个理论看起来是否合理?

例如滑稽,因为我没有任何铸件。

解决方案

从C ++的非活动成员中读取在C ++中是未定义的。 (在C99和C11中是合法的)。



因此,总而言之,编译器不需要假设/记住任何东西。



标准:


N4140§9.5[class.union] / 1

联合,非静态数据成员中的至多一个可以在任何时间是活动的,即,最多一个非静态数据成员的值可以随时存储在联合中。



I think I'm really asking: is aliasing "transitive"? If the compiler knows that A might alias B, and B might alias C, then surely it should remember that A might therefore alias C. Perhaps this "obvious" transitive logic isn't required however?

An example, for clarity. The most interesting example, to me, of a strict-aliasing issue:

// g++    -fstrict-aliasing -std=c++11 -O2
#include <iostream>

union
{   
    int i;
    short s;
} u;
int     * i = &u.i;

int main()
{   

    u.i = 1; // line 1
    *i += 1; // line 2

    short   & s =  u.s;
    s += 100; // line 3

    std::cout
        << " *i\t" <<  *i << std::endl // prints 2
        << "u.i\t" << u.i << std::endl // prints 101
        ;

    return 0;
}

g++ 5.3.0, on x86_64 (but not clang 3.5.0) gives the above output, where *i and u.i give different numbers. But they should give exactly the same number, because i is defined at int * i = &u.i; and i doesn't change.

I have a theory: When 'predicting' the value of u.i, the compiler asks which lines might affect the contents of u.i. That includes line 1 obviously. And line 2 because int* can alias an int member of a union. And line 3 also, because anything that can affect one union member (u.s) can affect another member of the same union. But when predicting *i it doesn't realise that line 3 can affect the int lvalue at *i.

Does this theory seem reasonable?

I find this example funny because I don't have any casting in it. I managed to break strict-aliasing with doing any casting.

解决方案

Reading from inactive member of a union is undefined in C++. (It's legit in C99 and C11).

So, all in all, the compiler isn't required to assume/remember anything.

Standardese:

N4140 §9.5[class.union]/1

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

这篇关于违反严格混叠,即使没有任何铸造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆