4

2つのスレッド間で変数を共有しています。そして、最適化を避けるためにvolatileを使用します。

ただし、strcpyに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");

}

一方、volatileをサポートするために独自のstrcpyを作成することもできます。しかし、これは奇妙です。もしそうなら、私はvolatileを使用するたびに、独自のI / Oストリーム(またはそれらの複雑な関数)を作成する必要があるのでしょうか?

答えてくれてありがとう。

4

2 に答える 2

4

どうやら、「揮発性」の意味を明確に理解していないようです。意味は多かれ少なかれ「コンパイラさん、他の誰かがこの変数を変更することに注意してください。あなたのコードがそれを書かない限り、値が一定のままであると仮定することはできません。さらに、他の誰かがこの変数を見ているかもしれないので、私が書くときこの変数は、重要ではない仮定で奇妙なことをしないでください。それを見ている他の人にとっては重要なので、私があなたに書いてほしいことを書いてください。

「揮発性」を使用することが重要なのはいつですか? 一般的な例を次に示します。

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

void mainloop()
{
    stopflag = 0;
    while (!stopflag)
    {
       ...
    }
}

3 つのドットのコードが未知の実装を持つ関数に決して触れ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 変数を使用することが実際にはしばしば可能でしたが、現在ではこれは誤りです。

バッファが実際に他の人によって読み書きされていることを伝えることに本当に興味があるようですが、この場合、バッファのアドレスは公開されているため、関数の呼び出し時に(インライン化されているか、既知の実装コードがない限り)、コンパイラはバッファの内容が変更されたか、不明なコードによって読み取られる可能性があると想定してください。

スレッド同期プリミティブが適切な方法で宣言され、これがあなたの場合にも当てはまることを保証するに違いありませstrcpyん(インライン化されている場合でも)。

于 2012-07-25T06:05:48.443 に答える
0

一部の場所 (スレッドの使用中) で最適化を実行したくない場合は理解できます。そのために「volatile」キーワードを使用します。

MSDNを参照してください

ポインターが指すオブジェクトを const または volatile として宣言するには、次の形式の宣言を使用します。

const    char *cpch;
volatile char *vpch;

ポインターの値 (つまり、ポインターに格納されている実際のアドレス) を const または volatile として宣言するには、次の形式の宣言を使用します。

char * const    pchc;
char * volatile pchv;

したがって、(必要に応じて)使用できます

"strcpy(serName, (char *)vptr);"  or " char*  volatile vptr = (char*) name;"

上記は、最適化を抑制して実行するコードのソリューションであり、エラーも発生しません。これで、完全な I/O を自分で実装する必要がなくなります:)

これは私にとってはうまくいきました。うまくいけば、それもあなたに役立ちます...

于 2012-07-25T05:35:16.733 に答える