2011-01-07 16 views
2

は、私はそれを実行する場合は罰金コンパイルしても問題なく動作しますが、私はVStudio.Butからそれを実行する場合にのみ、CWinAppのclass.Itでダイアログをceateすることです直接実行時エラーが発生し、プログラムがクラッシュしました。奇妙な問題MFCのC++

CMyDialog dlg; 
m_pMainWnd = (CWnd*)&dlg; 
dlg.DoModal(); 

しかし、私が下のコードを使用した場合、すべてが問題ありません。この動作は分かりません。

CMyDialog *dlg=new CMyDialog(); 
m_pMainWnd = (CWnd*)dlg; 
dlg->DoModal(); 

このタイプのものは、他の過去のC++(非MFC)プロジェクトでも何度も起こりました。 これを私に指定してください。

+0

問題が発生した場合、最初のケースからコールスタックを送信できますか? –

+1

私は実際に問題を理解しましたが、ここではコールスタックです(リリースモードでのエラーのみ)。 > \t ntdll.dllの!7c911e58()\t \t [フレームは、以下の間違ったおよび/または欠落している可能性があり、ntdll.dllのためにロードされていないシンボル] \t \t ntdll.dllの!7c918251()\t \t ntdll.dllの!7c911c76 ()\t \t ntdll.dllの!7c911538()\t \t ntdll.dllの!7c9106eb()\t \t ntdll.dllの!kernel32.dllの!7c801a24()\t \t 7c9140bb()\t \t kernel32.dllの!7c801a4f()\t \t ntdll.dllの!7c90e234()\t \t kernel32.dllの!7c8110db()\t \t ...他また、コメントサイズStackOverflowのオーバーフロー \t ... – YAHOOOOO

+0

このような場合、私は通常、クラッシュ直後に "デバッグ"を選択します。 Visual StudioがDEBUGバージョンで開かれていると仮定すると、実行ファイルをダブルクリックしても、クラッシュ後にプログラムをデバッグして問題の最下部に到達することができます。 –

答えて

2

は(DLGがスコープ外になったとき)最初のケースでは、オブジェクトが破棄されているが、それでもm_pMainWndによって指されます。 m_pMainWndが使用され、存在しなくなったオブジェクトにアクセスする可能性があります。

変更最初の例に:

CMyDialog dlg; 
m_pMainWnd = (CWnd*)&dlg; 
dlg.DoModal(); 
m_pMainWnd = NULL; 

これで問題が解決した場合、あなたは後者の場合にはそれで逃げた理由は、オブジェクトが(MFC、m_pMainWndがそれを指しているためものの、破壊されていなかったということですプログラムのシャットダウン時にあなたのためにそれを破壊することができ、実際に、他の場合には、クラッシュの原因になるかもしれません)。

+0

レオに感謝しますが、VS2008のコンパイル時に最初のケースがうまく動作する理由を教えてください。 – YAHOOOOO

+0

もう1つの事は、私は2日ago.the問題は、私はagain.andをコンパイルするときにも私はexeファイルをc:\ドライブに置くときにそれがうまく動作するが、他のフォルダそれは妙にクラッシュします(第1の場合)。 – YAHOOOOO

+0

解放されたオブジェクトにアクセスすることによって問題が発生した場合は、ポインタが以前に離れてしまった可能性があります(ポインターがクラッシュを引き起こしたデータを含まない読み取り可能なメモリを指していたため、それ以前のオブジェクトの状態は削除されていましたが)、プログラムの一部の変更が起こって、ちょっとしたことが起こり、クラッシュするようになっています。しかし、ちょうど推測です。ポインタをNULLに設定すると問題が解決されますか? –

1

これら2つのコードブロックの主な違いは、最初はdlgがブロックの最後で破棄され、2番目のブロックでは破棄されないことです。

あなたのプログラムの残りの部分が与えられた場合、それが宣言されているブロックの最後にまだdlgが必要ですか?その場合は、2番目のブロックのようなものを使用する必要があります。

また、DoModalが(直接的または間接的に)delete(this)を呼び出す可能性があります。その場合、dlgnewで行う必要があります。

+0

AFAIK 'DoModal'はそれをしません。私はスタック上にダイアログを作成し、私が覚えている限り、MFCで 'DoModal'を呼び出しました。 –

1

問題は、ダイアログを閉じたときにはもう存在しませんウィンドウにm_pMainWndを設定することで、これは一般的に前にダイアログ破壊を起こる、あなたがダイアログを閉じたときだけ(ときDoModal戻ります)。

私はダミーのウィンドウを作成し、メインウィンドウとしてそれを使用することによって、この問題を解決:

class CDummyWindow : public CFrameWnd 
{ 
public: 
    CDummyWindow() 
    { 
     Create(NULL, NULL); 
    } 
}; 

Class::InitInstance() 
{ 
    ... 
    CDummyWindow win; 
    m_pMainWnd = &win; 
    ... 
    return FALSE; 
} 

はあなたreturn FALSEアプリを停止すべきことを示すことを確認してください。