【问题标题】:Strict pointer aliasing: is access through a 'volatile' pointer/reference a solution?严格的指针别名:通过“易失性”指针/引用访问是一种解决方案吗?
【发布时间】:2010-06-05 19:50:14
【问题描述】:

a specific problem 之后,我想知道它是一个正确的解决方案、解决方法/hack 还是完全错误。

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

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 上确实解决了我的问题。

【问题讨论】:

  • 这个问题不是显然是 C++ 特定的。 C++ 风格的转换可以用 C 轻松重写。
  • @curiousguy 但是 C 和 C++ 有不同的语言规则
  • @MattMcNabb WRT volatile 有何不同?

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


【解决方案1】:

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

假设 T 是一个 POD。那么,正确的做法是

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

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

【讨论】:

  • “Volatile 无法帮助您避免此处未定义的行为”——为什么?你有这个声明的来源吗?
  • C++ 标准,第 3.10 节第 15 段是您需要查看的关于严格别名的地方。没有提到涉及 volatile 的异常。
  • 在某些情况下它不是未定义的行为。例如struct A { int a; }; int main() { X x; *reinterpret_cast&lt;int*&gt;(&amp;x) = 10; } 很好并且根据9.2/17 完美定义。对象是int类型的,左值也是volatile int类型的,所以别名很好。
  • @Johannes:我并不是要暗示它总是未定义的行为。我只是想说 volatile 对 3.10/15 没有任何影响。
  • 如果目标没有声明的类型,并且下一次读取的类型与源的有效类型不匹配,则不能保证使用 memcpy。如果要编写代码“oprimization proof”,则必须以一种不能被解释为对字符数组进行操作的方式加载和存储单个字符。
【解决方案2】:

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

嗯,关于volatile 的任何内容在标准中都有些不清楚。我基本同意你的回答,但现在我有点不同意。

为了理解volatile 的含义,该标准对于大多数人来说并不清楚,尤其是一些编译器编写者。最好这样想: 在使用volatile 时(并且仅在使用时),C/C++ 几乎是高级程序集

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

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

当然,在没有显式 LOAD 或 STORE 的情况下,编译器只会发出暗示 LOAD 或 STORE 的指令。

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

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

【讨论】:

  • -1:首先,这不是论坛;我们不会在答案中解决其他答案。如果您认为自己有更好的答案,请写下针对该问题的答案。其次,更重要的是,“标准中关于 volatile 的任何内容都有些不清楚。”不,不是。该标准非常清楚地说明了 volatile 和 non-volatile 如何在抽象机方面发挥作用。
  • @NicolBolas "其次,更重要的是,“标准中关于 volatile 的任何内容都有些不清楚。”不,不是。" 很多人认为它是非常不清楚。如果你觉得很清楚,请解释一下是什么意思,我的解释是正确的。
  • @NicolBolas "首先,这不是一个论坛;" 除了它是一个论坛。我们正在讨论事情。这是论坛的定义。 “我们不会在答案中解决其他答案。”所以我应该在评论中讨论这个问题,然后有人会告诉我我在评论中讨论了太多事情......
  • “所以我应该在评论中讨论这个,然后有人会告诉我我在评论中讨论了太多东西。”确切地。这就是我们如何将讨论排除在此问答网站之外,从而保持对问题的关注。我们通常不希望人们在答案中解决这样的另一个答案;我们希望重点是回答这个人的问题。你承认卖力做到了。
  • volatile 访问的行为是实现定义的,因此实现有可能以不防范别名的方式定义行为-相关的UB。由理智成熟的个人编写的编译器应该可以使用不同类型编写和读取volatile 位置。唉,一些编译器编写者宁愿寻找借口将某些东西视为未定义的行为,也不愿生成有用的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-22
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多