• ベストアンサー

グローバル変数が正常に参照できない?

Windows2000、VC++6.0 でMFCを使ってダイアログベースのEXEを作っています。 以下のようにグローバル変数をループ処理の終了条件に使ってみたのですが、Release版でビルドしたEXEだと意図した動作となりませんでした。 何か原因について心当たりのある方がいればご教授願います。 ------------------------------------------- BOOL bThreadEndFlag; // 外部変数 ●FuncA()関数でスレッドを作成します。 FuncA() {  bThreadEndFlag = FALSE;  CreateThread(..., ThreadFunc, ...);  Sleep(60000);  bThreadEndFlag = TRUE;  ◆     ・     ・ } ●スレッドではフラグがFALSEの間ループします。 ThreadFunc() {  while(bThreadEndFlag == FALSE ) {   X = Y;   ★  } } ------------------------------------------- 上記ではスレッド作成後、60秒後にはフラグがTRUEになり、スレッドが終了することを想定した造りになってます。 しかし、実際にはループ処理が終わらず、スレッドが終了しませんでした。 論理的にはちょっと理解できません。。。 いろいろ試して、以下の場合は正常に動作しました。 (1)コードは全く同じままで、Debug版でビルドした場合はOKでした。 (2)★の部分に「Sleep(0)」を追加した場合はRelease版でもOKでした。 <備考> ◆の位置でフラグの値がTRUEになっていることは確認しました。

質問者が選んだベストアンサー

  • ベストアンサー
noname#4564
noname#4564
回答No.2

> あとは、最適化ですかね?怪しいのは。 > なんかオプションあった気もしますが。 > 最適化について評価したところ、「実行速度」指定のみ > NGで、他の指定ではOKでした。 ウラを取ってませんが、山カンで、volatile ・・・かな・・・?

参考URL:
http://www.google.co.jp/search?hl=ja&ie=UTF-8&oe=UTF-8&c2coff=1&q=C%E8%A8%80%E8%AA%9E+volatile&lr=lang_ja
nabezo-
質問者

お礼

アドバイス、ありがとうございました。 私もいろいろなサイトを探して、volatile に辿り着きました。 恥ずかしながら、今まで volatile を知りませんでした。 早速、「実行速度」の指定で、変数を volatile宣言して試したところOKでした。 勉強になりました。

その他の回答 (3)

回答No.4

volatileキーワードにたどり着かれたということですので、以下の部分に関して... 『ただ、自分としては「最適化」によりプログラムが論理的に動作しないのは解せないです。。。 もし最適化について詳しく、今回の事象が発生する仕組みについて教えていただけると幸いです。』 お使いのコンパイラは、while節(つまり"{"と"}"とに挟まれた処理)の実行によって、bThreadEndFlagが変更されることはないと考えました。(volatileが付いていない変数ですからね。) したがって、最初の1回目の条件判定はおこなうでしょうが、ループの2回目以降の条件判定は不要であると判断しました。 実行速度優先なので、この不要と判断した部分をアセンブラに落とさなかったのです。 出来上がったバイナリを逆アセンブルして、アセンブラを読むことができればこのことを検証できます。 参考まで。

nabezo-
質問者

お礼

回答ありがとうございました。 その後、私も最適化について勉強し、volatile を知らずに使わなかった自分が悪かった、と納得できました。

  • 405
  • ベストアンサー率50% (17/34)
回答No.3

スレッド間で変数を共有するには、微妙なタイミングが問題になると思います。 デバッグ版やリリース版やsleepを入れる等で正常に動作したりしなかったりするのは、 この微妙なタイミングがズレる事によって起こっていると思います。 私は良く、イベントハンドルを利用して回避していますが、 とりあえず↓を参考にしてみてください。 http://www.kumei.ne.jp/c_lang/sdk/sdk_88.htm

参考URL:
http://www.kumei.ne.jp/c_lang/sdk/sdk_88.htm
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

本当に60秒後にフラグが変わったことを確認できましたか? おそらく、作成したスレッドが制御を移していないためと思われます。 スレッドの制御はOSが行っていますが、このようなソースだと、制御が移らないことがあります。 なので、明示的に別のスレッドに制御を移す ためにSleepを入れることが必要になります。 あとは、最適化ですかね?怪しいのは。 なんかオプションあった気もしますが。

nabezo-
質問者

補足

素早い回答ありがとうございます。 >本当に60秒後にフラグが変わったことを確認できましたか? はい、ログを入れてフラグが 0 から 1 に更新されたことを確認しました。 最適化について評価したところ、「実行速度」指定のみ NGで、他の指定ではOKでした。 アドバイスありがとうございました。 ただ、自分としては「最適化」によりプログラムが論理的に動作しないのは解せないです。。。 もし最適化について詳しく、今回の事象が発生する仕組みについて教えていただけると幸いです。