“解引用类型冲突指针将破坏严格别名规则”警告 [英] "dereferencing type-punned pointer will break strict-aliasing rules" warning
问题描述
我使用一个代码,我将枚举*转换为int *。这样的东西:
enum foo {...}
...
foo foobar;
int * pi = reinterpret_cast< int *>(& foobar);
在编译代码(g ++ 4.1.2)时,我收到以下警告消息:
取消引用类型冲突指针将破坏严格别名规则
我google了这个消息,发现只有当严格别名优化开启时才会发生。我有以下问题:
- 如果我留下此警告的代码,它会产生潜在的错误代码吗?
- 有没有办法解决这个问题?
- 如果没有,是否可以关闭源文件内的严格别名(因为我不' t想关闭所有源文件,并且我不想为此源文件制作单独的Makefile规则)
按顺序:
-
是的。 GCC将假设指针不能进行别名。例如,如果您通过一个分配,然后从另一个读取,GCC可能作为优化,重新排序读取和写入 - 我已经看到这种情况在生产代码,这是不愉快的调试。
-
几个。您可以使用联合来表示需要重新解释的内存。您可以使用
reinterpret_cast
。你可以在重新解释内存的地方通过char *
进行转换 -char *
被定义为能够别名任何东西。您可以使用具有__属性__((__ may_alias __))
的类型。您可以使用-fno-strict别名来全局关闭别名假设。 -
__ attribute __((__ may_alias __))$ c
p>对于你的特定例子,注意枚举的大小是不明确的; GCC通常使用可用于表示它的最小整数大小,因此将指向枚举的指针重新解释为整数可能会在生成的整数中留下未初始化的数据字节。不要这样做。为什么不直接转换为适当大的整数类型?
I use a code where I cast an enum* to int*. Something like this:
enum foo { ... }
...
foo foobar;
int *pi = reinterpret_cast<int*>(&foobar);
When compiling the code (g++ 4.1.2), I get the following warning message:
dereferencing type-punned pointer will break strict-aliasing rules
I googled this message, and found that it happens only when strict aliasing optimization is on. I have the following questions:
- If I leave the code with this warning, will it generate potentially wrong code?
- Is there any way to work around this problem?
- If there isn't, is it possible to turn off strict aliasing from inside the source file (because I don't want to turn it off for all source files and I don't want to make a separate Makefile rule for this source file)?
And yes, I actually need this kind of aliasing.
In order:
Yes. GCC will assume that the pointers cannot alias. For instance, if you assign through one then read from the other, GCC may, as an optimisation, reorder the read and write - I have seen this happen in production code, and it is not pleasant to debug.
Several. You could use a union to represent the memory you need to reinterpret. You could use a
reinterpret_cast
. You could cast viachar *
at the point where you reinterpret the memory -char *
are defined as being able to alias anything. You could use a type which has__attribute__((__may_alias__))
. You could turn off the aliasing assumptions globally using -fno-strict-aliasing.__attribute__((__may_alias__))
on the types used is probably the closest you can get to disabling the assumption for a particular section of code.
For your particular example, note that the size of an enum is ill defined; GCC generally uses the smallest integer size that can be used to represent it, so reinterpreting a pointer to an enum as an integer could leave you with uninitialised data bytes in the resulting integer. Don't do that. Why not just cast to a suitably large integer type?
这篇关于“解引用类型冲突指针将破坏严格别名规则”警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!