严格的指针别名:是通过'volatile'指针/引用访问解决方案吗?

时间:2010-06-05 19:50:15

标签: c++ volatile strict-aliasing type-punning

紧跟a specific problem,自我回答并对其发表评论,我想了解它是否是一个正确的解决方案,解决方法/黑客攻击或者只是错误。

具体来说,我改写了代码:

T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
  ...

如:

T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
  ...

指针的volatile限定符。

我们假设在我的情况下将T视为int是有道理的。这是通过volatile引用解决指针别名问题吗?

作为参考,来自规范:

  

[注意:volatile是一个提示,以避免攻击性   涉及对象的优化,因为对象的值可能   通过实现无法检测的方式进行更改。见1.9   详细的语义。通常,volatile的语义是有意的   在C ++中与在C中相同。 - 结束语]

编辑:

上述代码确实至少在GCC 4.5上解决了我的问题。

2 个答案:

答案 0 :(得分:15)

Volatile无法帮助您避免未定义的行为。所以,如果GCC对你有用,那就很幸运了。

我们假设T是POD。然后,正确的方法是

T x = …;
int i;
memcpy(&i,&x,sizeof i);
if (i==0)
  …

有!没有严格的别名问题和没有内存对齐问题。 GCC甚至将memcpy作为内部函数处理(在这种情况下不插入函数调用)。

答案 1 :(得分:-4)

  

Volatile无法帮助您避免未定义的行为。

嗯,关于volatile的任何内容在标准中都有些不清楚。我大多同意你的回答,但现在我想稍微不同意。

为了理解volatile的含义,大多数人都不清楚标准,特别是一些编译器编写者。最好考虑一下: 使用volatile时(仅当时),C / C ++几乎是高级程序集

当写入volatile左值时,编译器将发出一个STORE或多个STORE(如果一个不够)(volatile并不意味着原子)。

当写入volatile左值时,编译器将发出一个LOAD,如果还不够,则发出多个LOAD。

当然,如果没有明确的LOAD或STORE,编译器只会发出暗示LOAD或STORE的指令。

sellibitze提供了最佳解决方案:使用memcpy进行位重新解释。

但如果所有对内存区域的访问都是使用volatile左值完成的,则非常清楚严格的别名规则不适用。这是你问题的答案。