プログラムを実行した後、閉じるとDebug Assertion Failedと出た後
MFC42D.DLLにエラーが発生しましたと二回でてきます。デバッグを見てみると
// CString
_AFX_INLINE CStringData* CString::GetData() const
→ { ASSERT(m_pchData != NULL); return ((CStringData*)m_pchData)-1; }
のところと、
#ifndef _AFX_NO_OCC_SUPPORT
// cleanup control container,
// including destroying controls
→ delete m_pCtrlCont;
// cleanup control site
if (m_pCtrlSite != NULL && m_pCtrlSite->m_pWndCtrl == this)
m_pCtrlSite->m_pWndCtrl = NULL;
のところです。これは何をいっているのでしょうか?どなたかわかる方教えていただけないでしょうか。よろしくお願いいたします。
そこで止まったときに、コールスタックを表示して、
上から順番にあなたの作ったコードを探してそこをクリックしましょう。
あなたのコードが出てきたら、そこが原因である可能性が高いです。
コールスタックに自作コードの位置が出ないようなら、
何らかの処理中にメモリを破壊している可能性が高いです。
メモリを破壊した結果がたまたま終了時にエラー検出されている、ということ。
それならば全面的にコードをチェックする必要があると思われます。
警告レベルを上げてコンパイルし全警告を確認する等してください。
REE,tetrapodさん返信ありがとうございます。エラーが発生したあとデバッグを見るのは表示されるのでわかるのですが、これが自分で作ったプログラムのどのコードにあたるのかよくわかりません。コールスタックというのはどうすればできるのでしょうか?あとコード位置はどうすればわかるのでしょうか?初歩的なことを質問してすみません。よろしくお願いいたします。
VSのバージョンがわかりませんが、とりあえずVS6で。
表示−デバッグウィンドウ−コールスタックでコールスタックウィンドウが表示されます。
ここには、ステップ実行などをおこなっている場合、その地点までの、
関数のコールされた順番が表示されます。
(厳密には少し違うのかな。上手く表現できない。。。)
例えば、FuncA()という関数の中で、別のFuncB()という関数をコールし、
さらにそのFuncB()の中で新たな別の関数FuncC()を呼んでいて、
現在ステップ実行で、そのFuncC()のコードのところに来ている場合、
だいてい、次のような感じにコールスタックウィンドウに表示されます。
----ここから----
FuncC()
FuncB()
FuncA()
----ここまで----
これはあくまでかなり適当なれいですが、このコールスタックウィンドウを見ると、
現在はFuncC()という関数の中を実行しており、そのFuncC()は別のFuncB()という
関数の中からコールされており、さらにそのFuncB()はFuncA()の中からコールされている
というのが分かります。
で、標準ライブラリの関数(例えばmemcpy())などで落ちた場合でも、
その関数がどこで呼ばれているかを順番に戻っていき、自分が作成した関数(コード)
の部分がみつかったら、そのあたりが、バグの原因の可能性が高いです。
ここで、tetrapodさんが述べらているように、このコールスタックのところに、
自分で作成した関数名が全くでてこないようなら、このどの順番に関数がコールされているかを
記憶しているところ(コールスタック)自体がオーバフローなどにより、
破壊されていますので、その場合は、コールスタックを表示したまま、
地道にステップ実行を繰り返し、どの地点でコールスタックの表示がおかしくなるか、
確認して下さい。
#長文になり、あまり上手く説明できていないかもしれませんが、こんなもんで。
返信ありがとうございます。コールスタックを表示させたときこんな感じででてきました。
CString::GetDate() line 122 +34byte
CString::~CString() line208 + 8byte
C****Dlg::~C****Dlg()+71bytes
C****App::InitInstance() line 82 +25bytes
AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x81b6ae59, int 1) line 39 +11bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x81b6ae59, int 1) line 30
WinMainCRTStartup() line 330 + 54 bytes
KERNEL32! bff7bb67()
KERNEL32! bff7ba19()
KERNEL32! bff7a3d2()
この場合は
CString::GetDate() line 122 +34byte
CString::~CString() line208 + 8byte
C****Dlg::~C****Dlg()+71bytes
C****App::InitInstance() line 82 +25bytes
が自分のコードであるから、ここを直せということですよね?その他はどうにも覚えがないのです。しかし
CString::GetDate() line 122 +34byte
CString::~CString() line208 + 8byte
の文を削除してみようとするとVS自体を(include\Afx.inlとなっている)を書き換えてしまいそうです。
C****App::InitInstance() line 82 +25bytes
の行をみたのですが、特に間違ってる様子もないので…。
CString::GetDate() line 122 +34byte
CString::~CString() line208 + 8byte
は削除してもいいものなのでしょうか?
またはもっと別に原因があるのでしょうか?おねがいします 。
ライブラリ関数なり MFC 関数なりを誤った使い方で呼び出すと
例 : sprintf(NULL, NULL); とか
エラー報告はライブラリ関数の中で行われます。
ですが、もちろんライブラリ関数がバグっているわけではありません。
>は削除してもいいものなのでしょうか?
いけないにきまっています。
そこで起きたエラーの原因は、まず 99.9999% くらいまであなたのプログラムのバグです。
コールバック表の読み方ですが
C**Dlg::~C**Dlg
C**App::InitInstance
から InitInstance 中で使っている C**Dlg の処分中に失敗していることがわかります。
InitInstance で dlg を使うってことはダイアログベースであることも推測できます。
そしてさらに ~CString が呼ばれているので
「C**Dlg のメンバに CString があり、それに対して不正な何かをしている可能性が高い」
ことが判明しています。
よって「C**Dlg の CString のメンバを操作してる場所」を重点的に見直すべし。
という結論に達します。
# メモリ破壊が原因だと、上記は「破壊の結果」にすぎなかったりしますが...
ということで調べてみてください。
返信ありがとうございます。その後試行錯誤して、またフォルダ内を整理したところ、DEBUG内に残っていた更新されていないファイルのせいなのかもしれませんが、これを削除し、新たに起動させたところエラーがなくなりました。解決かどうかはわかりませんが、これで解決とさせていただきます。ありがとうございました。
ツイート | ![]() |