お世話になります。
ファイルをドラッグ&ドロップした時は、
ダイアログを起動する前にある処理を行って
終了するアプリケーションを作っています。
なぜかReleaseビルドした*.exeファイルだけが
アプリケーションエラーになってしまいます。
何が悪いのかまったく検討もつきません。
どなたかご指摘など頂ければ幸いです。
<環境>
WinXP,VC++6.0,MFC,Dialogベース
<やりたい事>
ファイルをドラッグ&ドロップした時は、
ダイアログを起動する前にある処理を行って
終了したい
<不具合現象>
Releaseビルドした*.exeファイルにドラッグ&ドロップした時だけ
問題が発生したため、.exe を終了します。 ご不便をおかけして申し訳ありません
というエラーメッセージがでます。
(Debugビルドはエラーメッセージは出ません。また処理は正常に行えているようです)
<ソースコード抜粋>
BOOL CApp::InitInstance()
{
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls();
#else
Enable3dControlsStatic();
#endif
C***Dlg dlg;
m_pMainWnd = &dlg;
if (__argv[1] != NULL) { // D&Dで起動の場合
// 処理
return FALSE;
}
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: ダイアログが <OK> で消された時のコードを
// 記述してください。
}
else if (nResponse == IDCANCEL)
{
// TODO: ダイアログが <キャンセル> で消された時のコードを
// 記述してください。
}
// アプリケーションを終了するために FALSE を返してください。
return FALSE;
}
まずは、デバッグ情報をつけてビルドするなり、
MessageBoxやファイル出力を使うなりして、
どの部分で落ちているのかを究明してください。
参考:
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200304/03040048.txt
情報有難うございます。
コード抜粋の処理の部分を全て
#if 0
#endif
でなくしてもエラーが出るのです。
return FALSE;
がまずいのでしょうか?
もう少し研究してみます。
余談です
>何が悪いのかまったく検討もつきません。
最近こういう誤変換が多いですね 見当>検討(自分でも誤変換の見落としがあるので気にな
りました)
あなたは、このコードのどこで問題が起きていると判断していますか?
その場合、何故そこだと判りましたか?
どこで起きたか判らないから投稿したんだという場合は、あなたが ”// 処理” と
あっさり記した所で起きている場合、あなた以外の誰にもここだろうと指摘する事が出来ません
更に、ダイアログが出る前後のどの時点でそのエラーメッセージが出るのかわからないので
(その事について何も触れていない)ここが怪しそうだと判断できそうにありません
デバッガーで追跡するか(Release ビルドでもデバッグは不可能ではありません(*))
メッセージボックスか実行ログを吐くコードかを随所に入れて動作を追跡するか
する事で範囲が絞れるでしょう
(* コンパイルオプションとリンクオプションとをデバッグシンボルを生成するように
設定すれば、あなたが作成したソースについてはデバッガ-で追う事が出来ます)
このところ、ソースを出してバグを取ってくださいという書き込みが
多いような気がしますね。
これだけじゃ何なので。
デバッグビルドとリリースビルドの違いについて、
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_common_problems_switching_from_debug_to_release_build.asp
にまとめられています。一読されてみてはいかがでしょう。
>return FALSE;
>
>がまずいのでしょうか?
CxxxApp::InitInstace() が失敗した事になりますから....
受取った(InitInstance() を呼び出した)方はこれ以上継続不能と判断するでしょうね
>見当>検討
すみません気をつけます。
>どこで起きたか判らないから投稿したんだという場合は、あなたが ”// 処理” と
>あっさり記した所で起きている場合、あなた以外の誰にもここだろうと指摘する事が出
>来ません
下記のようにしても起こるので処理は関係ないと思っています。
また、このif文をなくすと当然ダイアログが起動するので
この場合はエラーは起きません。
となれば、return FALSE;のタイミングの問題では?
と思いましたが、デバグ手段にアドバイスなどを頂きたく
投稿しました。
if (__argv[1] != NULL) { // D&Dで起動の場合
#if 0
// 処理
#endif
return FALSE;
}
>(* コンパイルオプションとリンクオプションとをデバッグシンボルを生成するように
> 設定すれば、あなたが作成したソースについてはデバッガ-で追う事が出来ます)
上記はMSDNのリリース ビルドのデバッグ情報の生成を有効にする
の事でしょうか?この方法は*.exeファイルにドラッグ&ドロップして
起動した際にも有効なDEBUG手段なのでしょうか?
> 下記のようにしても起こるので処理は関係ないと思っています。
> また、このif文をなくすと当然ダイアログが起動するので
> この場合はエラーは起きません。
> となれば、return FALSE;のタイミングの問題では?
> と思いましたが、デバグ手段にアドバイスなどを頂きたく
> 投稿しました。
ここまで分かっているのですから、Drag&Dropにこだわらず、
C***Dlg dlg;
m_pMainWnd = &dlg;
return FALSE;
というようなプログラムにしてデバッグすればよいのでは?
>m_pMainWnd = &dlg;
たぶん↑の位置が悪いと思われます。
return TRUE;
とするとメッセージは出なくなりました。
情報頂いた方々有難うございました。デバグ方法について
いろいろ勉強になりました。
しかし、2つ疑問が残ります。情報等頂ければ幸いです。
・DEBUGモードではエラーにならない理由
・MFCウィザードが生成するdialogベースのスケルトンが
InitInstance()でreturn FALSE;とする理由
>このところ、ソースを出してバグを取ってくださいという書き込みが
>多いような気がしますね。
そんなつもりでコードを添付したつもりはなかったのですが、
そのように受け取られたならお詫びいたします。
今後投稿の仕方を気をつけようと思います。
>return TRUE;
>
>とするとメッセージは出なくなりました。
そこで終わりにするのではなく、 return FALSE; の場合どうなっているのか
動作を追跡なさるとご自身のためにもなると思いますし、出来れば皆さんに
結果をご報告いただけると嬉しく思います
> >このところ、ソースを出してバグを取ってくださいという書き込みが
> >多いような気がしますね。
> そんなつもりでコードを添付したつもりはなかったのですが、
> そのように受け取られたならお詫びいたします。
> 今後投稿の仕方を気をつけようと思います。
あっ、いえ、そのような意図がお持ちでなかったのでしたら、私のほう
がおわび申し上げたいと思います。
> ・DEBUGモードではエラーにならない理由
これについては、先に示しました以下のURL
> デバッグビルドとリリースビルドの違いについて、
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_common_problems_switching_from_debug_to_release_build.asp
> にまとめられています。一読されてみてはいかがでしょう。
をどうぞ。
> ・MFCウィザードが生成するdialogベースのスケルトンが
> InitInstance()でreturn FALSE;とする理由
AppWizardが生成するコメントに記述されているとおり、
メッセージポンプを開始させないためです。
デバッガで追っていけば分かりますが…、
InitInstance()がエラー終了したにも関わらず、
m_pMainWndがNULLでない場合、
pThread->m_pMainWnd->DestroyWindow();
を呼び出して後始末しようとしています。
しかし、この場合、m_pMainWndに入っているのは、
ローカル変数dlgのポインタです。
すでにポインタが指す先のメモリは解放されており、
その部分にアクセスするためにアクセスエラーとなります。
DEBUG版で落ちないのは、
ポインタの指す先がたまたまアクセス可能な範囲内に
おさまっていたというだけでしょう。
> ・MFCウィザードが生成するdialogベースのスケルトンが
> InitInstance()でreturn FALSE;とする理由
これは、スケルトンのコメントの通りだと思います。
既に終わったアプリケーションのメッセージループを
動かしても無意味ですから。
本質を外したレスをしてしまいました。訂正させてください。
> ・MFCウィザードが生成するdialogベースのスケルトンが
> InitInstance()でreturn FALSE;とする理由
ダイアログベースのアプリケーションでは、DoModal()を呼んだ時点で、
ダイアログのメッセージループに入ります。
このループが終了すると、それがアプリケーションの終了になります。
ところで、InitInstance()がTRUEを返すとどうなるでしょうか?
CWinApp::Run()が走り、ダイアログが終了したにもかかわらず、またメッ
セージループが走り出します。
これを避けるため、アプリケーションを終了させるためにFALSEを返す
ようになっています。
ところで、上記についてはAppWizardによる生成コメントに書かれてい
た、と思いますが...
> ・DEBUGモードではエラーにならない理由
これについては、先に示しました以下のURL
> デバッグビルドとリリースビルドの違いについて、
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_common_problems_switching_from_debug_to_release_build.asp
> にまとめられています。一読されてみてはいかがでしょう。
に該当する点が、DoModal()呼び出しの有無によって顕在化しているの
でしょう。
一旦解決としましたが、いろいろと有用な情報を
頂けたのでもう少し調査してみました。
まさかInitInstance()を呼び出している側
をDEBUGする事になるとは思ってもいませんでした。
>InitInstance()がエラー終了したにも関わらず、
>m_pMainWndがNULLでない場合、
>pThread->m_pMainWnd->DestroyWindow();
>を呼び出して後始末しようとしています。
>しかし、この場合、m_pMainWndに入っているのは、
>ローカル変数dlgのポインタです。
>すでにポインタが指す先のメモリは解放されており、
>その部分にアクセスするためにアクセスエラーとなります。
下記のようにすることでエラーは出なくなりました。
C***Dlg dlg;
m_pMainWnd = &dlg;
if (__argv[1] != NULL) { // D&Dで起動の場合
// 処理
m_pMainWnd = NULL; ←追加
return FALSE;
}
>ところで、InitInstance()がTRUEを返すとどうなるでしょうか?
こちらに関してはデバッガで追いましたが私の勉強不足で
どうなるのか説明する事できません。
今後説明できるよう勉強していきたいと思います。
情報頂いた方々本当にに有難うございました。
おかげでいろいろと勉強になりました。
今後とも宜しくお願いします。