我在两个线程之间共享一个变量。我使用 volatile 来避免优化。
但是,它显示了一个错误,因为在 strcpy 中没有 volatile。 (如下)
如何正确修复此错误?
有人告诉我要通过类型抛弃 volatile。 但是,如果我抛弃了 volatile,那么我就失去了 volatile 的目的…… 最终可能会因优化而出现运行时错误......不是吗?
非常感谢。
(代码可以直接编译)
CRITICAL_SECTION CriticalSection;
HANDLE hEvent;
void __cdecl MyThread(void* name)
{
char serName[256];
volatile char* vptr = (char*) name;
EnterCriticalSection(&CriticalSection);
strcpy(serName, vptr); // error : cannot convert 'volatile'
// use (and not modify) name…
LeaveCriticalSection(&CriticalSection);
SetEvent (hEvent) ;
}
void main ()
{
char name[256] = "abcde";
hEvent = CreateEvent (NULL, false, false, NULL) ;
if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400) )
return;
_beginthread (MyThread, 0, name) ;
EnterCriticalSection(&CriticalSection);
// access name…
LeaveCriticalSection(&CriticalSection);
WaitForSingleObject (hEvent, INFINITE) ;
DeleteCriticalSection(&CriticalSection);
CloseHandle (hEvent);
system("pause");
}
另一方面,我可以编写自己的 strcpy 来支持 volatile。 但这很奇怪。 因为如果是这样,那么我每次使用 volatile 时都必须编写自己的 I/O 流(或那些复杂的函数)?
再次感谢您的回答。
最佳答案
显然您对“volatile”的含义没有清楚的理解。意思或多或少是“嘿编译器,请注意其他人会改变这个变量,所以你不能假设除非你的代码写入它,否则值将保持不变。此外,其他人可能正在观察这个变量,所以当我写到这个变量请不要在假设无关紧要的情况下做奇怪的事情,因为对于其他观看它的人来说很重要,所以只要写下我想让你写的,当我告诉你写的时候。”
什么时候使用“volatile”很重要?这是一个常见的例子:
volatile int stopflag; // flag will be set by an interrupt handler
void mainloop()
{
stopflag = 0;
while (!stopflag)
{
...
}
}
如果三个点中的代码从不触及 stopflag
并且从不调用具有未知实现的函数,那么编译器可能会试图避免读取循环中的标志,因为查看代码本身似乎根本不需要读取变量...只需设置并永远循环。
另一种情况可能是:
extern volatile unsigned char outloc; // monitored by hardware
...
// emit a wave pulse
for (int x=0; x<256; x++)
outloc = x;
如果没有 volatile
,编译器可能会试图将 0xFF
写入该位置,而不是写入所有中间值。
请注意,在现代硬件上使用volatile
进行线程同步是不够的。在今天的计算机中,通常 CPU 是多核的,因此写入和读取不再是原子操作。虽然在过去(在单核 CPU 上)实际上通常可以使用 volatile 变量进行线程同步,但现在这是错误的。
您似乎确实有兴趣说明 buffer 确实被其他人读写,但在这种情况下,缓冲区的地址是公共(public)的,因此在函数的任何调用中(除非它是内联的)或具有已知的实现代码)编译器必须假定缓冲区内容可能已更改或将被未知代码读取。
我敢打赌,线程同步原语是以正确的方式声明的,以确保在您的情况下也是如此(即使 strcpy
是内联的)。
关于c++ - 函数没有 volatile。怎么修?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11643116/