【问题标题】:Visual C++ VolatileVisual C++ 易失性
【发布时间】:2023-03-13 17:10:01
【问题描述】:

Visual C++ 中“volatile”的 MSDN 文档指出,写入具有“释放语义”,而读取具有“获取语义”,此外还确保读取始终从内存中读取,而写入始终相应地写入。

“volatile”的 C 规范包括第二部分(不要进行疯狂的优化),但不包括第一部分(内存栅栏)。

在 Visual C++ 中有没有什么方法可以只获得“C”易失性行为,而没有内存栅栏?

我想强制一个变量总是在堆栈上,在一个固定的位置,但我不想在每次分配给它时都承受内存栅栏的开销。

有没有什么简单的方法可以用 Visual C++ 源代码做到这一点?

【问题讨论】:

  • 我认为第一部分不是标准 C++ 行为。不过我不确定。
  • “我想强制一个变量总是在堆栈上,在一个固定的位置”,volatile 将如何帮助? FWIW,变量总是在一个固定的位置。 @Nawaz:不,第一部分不标准。
  • @Fernades 局部变量并不总是在一个固定的位置。可以消除局部变量,或者它们在堆栈上的地址可以位于不同的位置,具体取决于 PC 的位置。优化器可以做很多疯狂的事情。我想抑制这些优化。做到这一点的方法是使用“易失性”。但是,我不想要 Visual C++ 引入的非标准内存栅栏。
  • 编辑为(希望)清楚地表明这是特定于 MS 的行为。实际上我认为它只适用于 Visual C++ 2005 及更高版本。
  • @ScottWisniewski:它更有可能有时在堆栈上,有时在寄存器中,而不是堆栈上的两个不同位置。但你肯定有道理。

标签: c++ visual-c++ volatile


【解决方案1】:

在 Visual C++ 中是否有任何方法可以仅获得“C”易失性行为,而无需内存栅栏?

在 x86 上,在对 volatile 内存位置的读取和写入操作时,没有在程序集级别创建内存栅栏,因为在该平台上,每个加载都有获取语义,每个存储都有释放语义。因此,对于 x86 上的 MSVC,volatile 指令仅指示编译器根据您是从标记为 volatile 的内存位置写入还是读取,来阻止加载和存储的重新排序。

您只会在 IA64 架构上招致内存栅栏的“惩罚”,因为该平台的内存排序模型并不能确保加载和存储的获取和释放语义。

请记住,此行为是特定于 MSVC 的,不是 volatile 的标准化语义。

更新:根据@ildjarn 的说法,您还会在 ARM 上看到带有 Windows 8 的内存栅栏,因为该平台还具有像 IA64 这样的弱排序内存一致性模型。

【讨论】:

  • 惩罚也适用于 ARM。
  • MSVC 能否在 ARM 上运行? ...我不知道你可以在 ARM 上运行 Windows 程序 ...
  • ARM 是 Windows 8 的主要平台,因此 MSVC11 也支持 ARM 作为主要架构。
  • 谢谢! IA64 没什么大不了的。在 Arm 上,是否可以抑制内存栅栏?
  • 没有人记得 Windows Mobile 了 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-04
  • 2012-02-22
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多