在C ++ 03中标准可观察行为(1.9 / 6)包括读取和写入易失性数据。现在我有了这段代码:
int main()
{
const volatile int value = 0;
if( value ) {
}
return 0;
}
正式初始化一个volatile变量然后读取它。 Visual C ++ 10发出的机器代码通过在那里推动dword来为堆栈腾出空间,然后将零写入该堆栈位置,然后读取该位置。
对我来说没有任何意义 - 没有其他代码或硬件可能知道本地变量的位置(因为它在自动存储中),所以期望变量可以由任何其他方读取/写入是不合理的所以在这种情况下它可以被淘汰。
是否允许删除此变量访问权限?访问易失性本地哪个地址不为任何其他方可观察的行为所知?
答案 0 :(得分:8)
线程的整个堆栈可能位于受保护的内存页面上,其中包含一个记录所有读取和写入的处理程序(当然也允许它们完成)。
但是,我认为MSVC并不关心是否或如何检测到内存访问。除其他事项外,它理解volatile
意味着“不要对这个对象应用优化”。所以它没有。它没有意义,因为MSVC对加速volatile
的这种使用不感兴趣。
由于它依赖于实现是否以及如何实际观察到可观察行为,我认为如果由于硬件的细节而知道无法检测到访问,则实现可以“作弊”。可以跳过没有物理上可检测到的影响的可观察行为:无论标准是什么,检测不合规行为的方法都限于物理上可能的行为。
如果某个实现无法符合林中的标准,并且没有人注意到,它是否发出声音?有点儿。
答案 1 :(得分:3)
这就是声明变量volatile
的重点:您告诉实现该变量可能会通过实现本身未知的方式更改或读取,并且实现应避免执行可能影响此类访问的优化
当同时声明变量volatile
和const
时,您的程序可能不会更改它,但它仍然可以从外部更改。这意味着不仅变量本身而且其上的所有读取操作都不能被优化掉。
答案 2 :(得分:2)
没有其他代码或硬件可能知道
你可以查看一个程序集(你刚刚做过!),找出变量的地址,并在调用期间将其映射到某些硬件。 volatile
意味着实施也有责任解释这些问题。
答案 3 :(得分:1)
易失性也适用于您自己的代码。
volatile int x;
spawn_thread(&x);
x = 0;
while (x == 0){};
如果x
不易变,这将是无限循环。
至于const。我不确定编译器是否可以使用它来决定。
答案 4 :(得分:1)
对我来说没有任何意义 - 没有其他代码或硬件可能 知道局部变量的位置(因为它是自动变量) 存储)
真的?因此,如果我编写一个x86模拟器并在其上运行代码,那么该模拟器将不知道该局部变量?
实现永远实际上知道以确保行为不可观察。
答案 5 :(得分:0)
我的回答有点晚了。无论如何,这句话
对我来说没有任何意义 - 没有其他代码或硬件可能 知道局部变量的位置(因为它是自动变量) 存储)
错了。在VC ++ 2010中,volatile或not之间的区别实际上是非常明显的。例如,在发布版本中,您无法将断点添加到通过优化消除的局部变量声明中。因此,如果您需要设置一个断点到一个变量声明,甚至只是为了在Debugger中看它的值,我们必须使用Debug build。要在Release版本中调试特定的局部变量,我们可以使用volatile关键字:
int _tmain(int argc, _TCHAR* argv[])
{
int a;
//int volatile a;
a=1; //break point here is not possible in Release build, unless volatile used
printf("%d\n",a);
return 0;
}