函数没有易失性。怎么修?

Ken*_*enC 5 c c++ volatile visual-c++

我在两个线程之间共享一个变量。我使用 volatile 来避免优化。

\n\n

但是,它显示了由于 strcpy 中没有 volatile 的错误。(如下)

\n\n

我怎样才能正确修复这个错误?

\n\n

有人告诉我要类型转换掉 易失性。\n但是如果我放弃易失性,那么我就失去了易失性的目的......\n最终可能会因优化而出现运行时错误......不是\'是吗?

\n\n

非常感谢。

\n\n

(代码可直接编译)

\n\n
\n\n
CRITICAL_SECTION CriticalSection;\n\nHANDLE hEvent;\n\nvoid __cdecl MyThread(void* name)\n\n{\n\nchar serName[256];\n\nvolatile char* vptr = (char*) name;\n\n\n\nEnterCriticalSection(&CriticalSection);\n\n\n\nstrcpy(serName, vptr); // error : cannot convert \'volatile\'\n\n// use (and not modify) name\xe2\x80\xa6\n\n\n\nLeaveCriticalSection(&CriticalSection);\n\nSetEvent (hEvent) ;\n\n}\n\n\n\n\nvoid main ()\n\n{\n\nchar name[256] = "abcde";\n\nhEvent = CreateEvent (NULL, false, false, NULL) ;\n\nif (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400) )\n\nreturn;\n\n\n\n_beginthread (MyThread, 0, name) ;\n\n\n\nEnterCriticalSection(&CriticalSection);\n\n// access name\xe2\x80\xa6\n\nLeaveCriticalSection(&CriticalSection);\n\n\n\nWaitForSingleObject (hEvent, INFINITE) ;\n\nDeleteCriticalSection(&CriticalSection);\n\nCloseHandle (hEvent);\n\nsystem("pause");\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

另一方面,我可以编写自己的strcpy来支持易失性。\n但这很奇怪。\n因为如果是这样,那么每次使用易失性时我都必须编写自己的I/O流(或那些复杂的函数)?

\n\n

再次感谢您的回答。

\n

650*_*502 4

显然你对“不稳定”的含义还没有清楚的了解。其含义或多或少是“嘿编译器,请注意其他人会更改此变量,因此您不能假设除非您的代码编写它,否则该值将保持不变。此外,其他人可能正在监视此变量,因此当我写入这个变量请不要用无关紧要的假设来做奇怪的事情,因为对于其他观看它的人来说很重要,所以只要写下我想让你写的内容以及当我告诉你这样做时。”

什么时候使用“易失性”很重要?这是一个常见的例子:

volatile int stopflag; // flag will be set by an interrupt handler

void mainloop()
{
    stopflag = 0;
    while (!stopflag)
    {
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)

如果三个点中的代码从不接触stopflag并且从不调用具有未知实现的函数,那么编译器可能会试图避免读取循环中的标志,因为查看代码本身似乎不需要读取变量根本...只是设置并永远循环。

另一种情况可能是:

extern volatile unsigned char outloc; // monitored by hardware

...
// emit a wave pulse
for (int x=0; x<256; x++)
    outloc = x;
Run Code Online (Sandbox Code Playgroud)

如果没有volatile编译器,则可能会想只写入0xFF该位置而不是写入所有中间值。

请注意,volatile在现代硬件上使用线程同步是不够的。在当今的计算机中,CPU 通常是多核的,因此写入和读取不再是原子操作。虽然在过去(在单核 CPU 上),实际上通常可以使用易失性变量进行线程同步,但现在这是错误的。

您似乎确实有兴趣告诉其他人确实正在读取和写入缓冲区,但在这种情况下,缓冲区的地址是公共的,因此在函数的任何调用中(除非它是内联的或具有已知的实现代码),编译器必须假设缓冲区内容可能已更改或将被未知代码读取。

我敢打赌,线程同步原语是以正确的方式声明的,以确保在您的情况下也是如此(即使strcpy是内联的)。