首页 文章

是否访问不能从C语言中的函数可观察行为外部访问的volatile变量?

提问于
浏览
6

在C 03中,标准可观察行为(1.9 / 6)包括读取和写入易失性数据 . 现在我有这个代码:

int main()
{
    const volatile int value = 0;
    if( value ) {
    }
    return 0;
}

它正式初始化一个volatile变量然后读取它 . Visual C 10发出机器代码,通过在那里推动dword在堆栈上腾出空间,然后将零写入该堆栈位置,然后读取该位置 .

对我来说没有任何意义 - 没有其他代码或硬件可能知道本地变量的位置(因为它在自动存储中),所以期望变量可以由任何其他方读取/写入是不合理的,所以它在这种情况下可以消除 .

是否允许消除此变量访问?访问易失性本地哪个地址不为任何其他方可观察的行为所知?

6 回答

  • 2

    对我来说没有任何意义 - 没有其他代码或硬件可能知道局部变量的位置(因为它在自动存储中)

    真?因此,如果我编写一个x86模拟器并在其上运行您的代码,那么该模拟器将不知道该局部变量?

    实现永远无法确定该行为是不可观察的 .

  • 8

    线程的整个堆栈可能位于受保护的内存页面上,其中包含一个记录所有读取和写入的处理程序(当然也允许它们完成) .

    但是,我不认为MSVC真的关心是否或如何检测内存访问 . 它理解 volatile 意味着,除其他外,"do not bother applying optimizations to this object" . 所以它没有意义,因为MSVC对加速 volatile 的这种使用不感兴趣 .

    由于它是依赖于实现的,是否以及如何实际观察到可观察的行为,我认为如果由于硬件的细节而知道无法检测到访问,则实现可以“作弊” . 可以跳过没有物理上可检测到的影响的可观察行为:无论标准说什么,检测不合规行为的方法都限于物理上可能的 .

    如果一个实现不符合森林中的标准,没有人注意到,它是否发出声音?之类的事情 .

  • 0

    这就是声明变量 volatile 的全部要点:您告诉实现该变量可能会通过实现本身未知的方式更改或读取,并且实现应避免执行可能影响此类访问的优化 .

    当声明变量 volatileconst 时,您的程序可能不会更改它,但它仍然可以从外部更改 . 这意味着不仅变量本身而且其上的所有读取操作都不能被优化掉 .

  • 1

    没有其他代码或硬件可能知道

    你可以查看一个程序集(你刚刚做过!),找出变量的地址,并在调用期间将其映射到某些硬件 . volatile 意味着实施也有义务解释这些问题 .

  • 1

    易失性也适用于您自己的代码 .

    volatile int x;
    spawn_thread(&x);
    x = 0;
    while (x == 0){};
    

    如果 x 不易变,这将是一个无限循环 .

    至于const . 我不确定编译器是否可以使用它来决定 .

  • 3

    我的回答有点晚了 . 无论如何,这句话

    对我来说没有任何意义 - 没有其他代码或硬件可能知道局部变量的位置(因为它在自动存储中)

    是错的 . 在VC 2010中,volatile或not之间的区别实际上是非常明显的 . 例如,在Release版本中,您不能将断点添加到通过优化消除的局部变量声明中 . 因此,如果您需要设置一个断点到一个变量声明,甚至只是为了在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;
    }
    

相关问题