開発環境:Windows2000 SP2
VC++6.0 SP4
MFC使用
初めまして。
会社で作成しているものなので内容を詳しく話すわけにはいきませんが、MFCのフレーム上に作
った実行用のボタンを押すたびにある別のEXEファイルを起動させた後、こちらの本当のプログ
ラムが走るようになっているものを作っています。ですが、この行為を何度か続けているうちに
マルチスレッドが生成できなくなってしまう現象が発生するようになりました。突き詰めてみた
ところどうも原因がメモリ破壊であり、それを発生させているのがShellExecuteのコマンドの
ところのようだと言うところまでわかりました。
そこで質問なのですが、『ShellExecute』の命令はメモリを破壊してしまうのでしょうか?それ
ともひとつのアプリケーションの起動中に別のアプリケーションを起動させるとメモリ破壊を起
こしてしまうのでしょうか?ほかには別に起動させているEXEファイルが悪いだけの可能性もあ
ります。ですがこちらの方はちょっと調べようがありません。なので切り分けのためにも
『ShellExecuteによるメモリ破壊の可能性』を知っておきたいのです。もしどなたかこの事に
ついて知っている事があれば教えてください。
もし別のアプリケーションの起動によるメモリ破壊だった場合、なにか解決方法ないし回避策の
ようなものを知っている場合も合わせて教えてください。
いきなりでしかも判りにくい質問かと思いますが、どうか皆様よろしくお願いします。
なんだかよくわからんけど、メモリの確保がうまくいっていないのかな?
SHGetMalloc()とFree()を試しに使ってみれば?
ShellExecute()でSHGetMalloc()を使ったことないから、責任はもてないけど・・・。
SP3 を適用するか、Windows Update で修正されるハズですが。
http://www.microsoft.com/japan/technet/treeview/default.asp?
url=/japan/technet/security/bulletin/ms02-014.asp
2行に分かれてしまいました…
実際は1行のURLです。
動作順序を簡略例を持って説明していただけませんか?
もう少しイメージ掴みたいのですが
たとえば
1 A.EXE(自分、常駐)
2 A.EXEのボタン
3 B.EXEを起動(実行待ち、終了待ちしない)
4 2・3を?回たとえば50回など回数はいつでも同じ回数でおかしくなるとか
こんな感じかな??
ほかに聞きたいことは
パラメータ
hwnd
親ウィンドウのハンドルを指定します。
このウィンドウは、アプリケーションが生成したすべての
メッセージボックスを受け取ります。
たとえば、アプリケーションはエラーが発生したときに、
メッセージボックスを使ってそのことを伝えることがあります。
と、こんなふうになっていると思いますが、A.EXE(自分)を渡してますか
それともべつのハンドル渡してますか
また、このハンドル使ってB.EXEが変なメモリ操作してませんか
メモリリーク起こしたまま終了しているとか
A.EXEに身に覚えのないメモリ確保がどんどん増えていくとか
こんなアドバイスでもう少し対象を絞り込むことできませんかね!!
cantoさん、情報ありがとうございます。まだそれを使うかどうか決まっていませんが、社内で
決定したら試させてもらいます。
suzukaさん、ありがとうございます。現在開発用のPCはネットにつなげられないので、つなげ
られるようになったら早速導入しようと思います。
woodさん、判りにくい説明ですみません。もう少し順を追って説明させてもらいます。
・Main.EXE(本来動かしたいEXE)
・Sub.EXE(実行ボタンを押すたびに起動するとあるメーカーのEXE。すぐに自動で閉じます。)
以上のように定義して、
1.Main.EXEを起動。(常にアクティブ)
2.実行ボタンをプッシュ。
3.Sub.EXEが起動。(約1秒ほどで自動的にクローズ)
4.スリープで1秒以上待ってから(特にSub.EXEの終了を確認していません)プログラムの実
行。
5.プログラムの終了。(Main.EXEは立ちあがったまま)
6.2へ戻る。
こんな感じです。この行為を3回以上行うと発生します。残念ながら必ず3回ではありません。も
っとも頻繁に起こるのは3回目なのですが、時々10回を越えても起きない場合があります。それ
でもいつかは必ずとまりますが。
メモリのリークは机上デバッグ、デバッグモードでのステップ実行などでの確認、タスクマネー
ジャによるメモリ使用量の変化などから、今のところはMain.EXEにはないことが解っていま
す。一方Sub.EXEは自分で作ったものではないのでタスクマネージャによる確認のみですが、こ
ちらもとくにリークを起こしているようには見えませんでした。
ハンドルですが、m_hWndとしてMain.EXEのハンドルを渡しています。これって問題になります
か?今までこの使い方では問題は発生しなかったのですが…。
これで少しは判り易くなったでしょうか?説明が下手ですみません。どうかよろしくお願いしま
す。
>ShellExecute
でなければいけない理由ありますか
CreateProcessにしてみても現象同じですか
見当違いかも知れませんが一応。
メモリリークが発生しない場合でもスレッドによる制御を行なっているプログラムで
スレッド内にブレイクポイントを置いたりすると止まることがありました。
(ブレイクポイントを置かなくてもVC上で実行するととまることもある)
書いてある事象は「スレッドが生成できなくなる」のようですので
ちょっと違うかもしれませんがスレッド使用のプログラムでは
デバッグするとなにかしら変なことが起きていたので・・・
デバッグフォルダやリリースフォルダに入っているexeファイルを実行しても
スレッドが生成されないのでしょうか?
見当はずれだったらごめんなさい。
>マルチスレッドが生成できなくなってしまう現象が発生するようになりました。突き詰
めてみた
>ところどうも原因がメモリ破壊であり、それを発生させているのがShellExecuteのコマ
ンドの
>ところのようだと言うところまでわかりました。
マルチスレッドが生成できなくなったというのは、どっから判断したのでしょうか?
マルチスレッド自体の作成の失敗か成功かは、そのスレッドの生成部分をデバッグすれば
わかりますよね?そこでは、どんなエラーがでているのでしょうか?
あとなぜ、ShellExecuteでのプロセスの作成がマルチスレッドの作成に関係あると判断し
たのでしょうか?
ちょっと、よくわからなかったので聞いてみました。
woodさんへ
CreateProcessは試してみた事がないので社内で検討の上、試してみようと思います。今は開発
用PCを使えない状態にあるので、返答はかなり後になると思いますが。
ちるさんへ
ご意見ありがとうございます。でもせっかくですが、今回の内容とは違う事です。この問題は明
らかにスレッドが生成されない(後述します)のが原因なのでスレッドの中身の問題ではないで
す。せっかくなのにすみません。
exeファイルを直接起動する方法ですが、ReleaseでもDebugでも同様の現象が出ます。あえて言
えばDebugの方が発生頻度が低いです。なので最適化のオプションをいじってみましたが、結論
は一緒でした。
ワルツさんへ
スレッドが生成されないと判断した方法ですが、AfxBeginThread()の命令でスレッドを生成す
るときにNULLを返したら生成に失敗したとみなしているからです。AfxBeginThread()の直後に
NULLの場合はメッセージボックスが立ちあがってエラーがあると知らせるようになっていて、
そこで判断しました。
ShellExecute()の命令が関係しているかを確かめた方法ですが、幸いこのShellExecute()はプ
ログラムのはじめの方で使っているので、ShellExecute()を行ったらプログラムを無理矢理終
了させるようにソースをいじってみたからです。この状態でも3回目以降にスレッドが生成され
ない現象が発生するのを確認しています。逆にShellExecute()無しならばこの現象は発生しな
い(ただしその場合全く別の問題が発生しますが、それはこちらの事なので省かせてもらいま
す。)ことも判っています。
メモリ破壊が原因であると判断した理由ですが、これは上記2つを踏まえて社内で検討したとこ
ろ、『スレッドが立ちあがらないのはメモリ破壊しかありえない』と言う結論に達したからで
す。
今すぐには確かめようのない状態なのですが、もしまだほかに何かあればご意見をお聞かせくだ
さい。よろしくお願いします。
皆さん、ご意見ありがとうございました。そしてごめんなさい。こちらの問題は別のところに原
因がありました。
原因は開発用PC自身のバグでした。詳しく言えませんがこれによりほかの増設したボードと見え
ないところでエラーが発生し、このたびの問題が発生していました。よってPCを変えてみたとこ
ろなんの問題もなく動作しました。
色々情報をくれた皆様には感謝しています。一応こちらでの問題はなくなりましたので解決とさ
せていただきます。ありがとうございました。