在c ++中,内存写入可以通过优化延迟,还是需要volatile?

时间:2016-02-07 18:36:50

标签: c++ volatile

我已经在这里阅读了几十个关于使用volatile的问题和答案,我为发布另一个而道歉但我不认为我已经看到了我正在寻找的东西

我有一个用C ++编写的Arduino微控制器库。我有一个填充缓冲区的ISR,当它完成时,它会设置一个标志,让外界知道有可用的数据。我有缓冲区,一个告诉缓冲区中有多少字节的变量,以及告诉世界缓冲区有数据的标志。一旦我设置了#34;我已经完成填充缓冲区"在ISR中,ISR将永远不会再次更改缓冲区或其长度,直到/除非我重新启用。

通常我已经将标志,缓冲区和长度值都声明为volatile,因为这是你在ISR例程中应该做的事情。

然而,一旦它充满,我会对该缓冲区进行大量处理,这意味着我会在一些潜在的优化中欺骗自己。在我的ISR之外,如果我的代码类似于

if (flag== FINISHED) {
  disable_my_ISR (); 
   /*do a bunch of stuff with the buffer*/
  reenable_my_ISR();
}

然后理论上我认为我不需要将缓冲区作为volatile。那是对的吗?正如我所说的那样,我的关注是我的#"用缓冲区做了很多事情"没有得到优化,因为缓冲区是易失性的。

我在这个论坛的任何地方看到的唯一其他答案是this one但是我不确定这种情况是否真的相同。

2 个答案:

答案 0 :(得分:2)

当您将某些内容标记为volatile时,您说它的值可能会在代码中的写入/读取之间发生变化。这正是ISR访问变量时可能发生的情况,因此您需要volatile

您的ISR与主要代码之间共享的任何变量都应为volatile。您的代码可能无法标记所有内容,但最终会回来咬你。

  

然后理论上我认为我不需要将缓冲区作为volatile。

不,如果主代码和ISR都使用了缓冲区,则需要将其标记为volatile。我想你可能会担心错过优化问题。您始终可以将volatile数组复制到普通数组中,进行处理,然后计算差异。

答案 1 :(得分:2)

甚至没有内存写入可以通过优化延迟 - 如果您的缓冲区未声明volatile,您的编译器可能会使用它删除任何代码。举个例子:

int myBuffer[5] = {0};
if(flag == FINISHED) {
    printf("%d", myBuffer[0]);
}

这可能总是打印0,即使您的ISR更改了缓冲区的值,因为编译器不知道ISR如何更改程序流并因此假设myBuffer[0]将使用时为0。