• ベストアンサー

【VC++6.0(MFC)】Access Violationの対応の仕方

いつも大変お世話になっております。 VC++初心者です。 現在、VC++6.0(MFC)で先人が作成したソースを改良しています。 デバグモードで動かすと、 以下のメッセージが表示されるのですが、 どのように対応すればよいか、教えていただけませんでしょうか。 「例外処理 (初回) は XXXX.exe (NTDLL.DLL) にあります: 0xC0000005: Access Violation」 (※XXXXはプロジェクト名です。) (※デバグモードで動かすと同時に上記エラーが出力されます。) 上記のエラーが出ていても動かせるのですが、 デバグモード時に、メニューの「デバッグ」、「例外処理」で 「 Access Violation」の設定を 「ハンドルされてなければ停止」から「常に停止」に変更すると、 最初の画面も開けずに、混合モード画面の 7C95AB0A inc dword ptr [eax+10h] という箇所で必ず止まって、落ちてしまいます。 ここから、どのように対処すればよいか、ご教授頂きたくお願いします。

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

  • ベストアンサー
回答No.7

申し訳ありませんが、はっきり言って私にはお手上げ状態です。 混合モード画面で落ちた所から、コールスタック?スタックウィンドウ?(関数コールの履歴)を辿って、原因となったコードの箇所を見つければ、先に進むかもしれません。

yuki7091
質問者

お礼

ご回答、ありがとうございます。 これまでのご対応ありがとうございました。 別件で質問させて頂く機会がある時は また、よろしくお願いします。

yuki7091
質問者

補足

回答者の皆様、 今まで私の質問に対応して頂き、ありがとうございました。 一度、この質問は閉じさせて頂きます。 なお、本件のつづき(?)は http://okwave.jp/qa5323629.html で引き継ぎます。

その他の回答 (6)

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.6

BROWSEINFO構造体のlpfnはNULLでも問題ないはずです。 http://msdn.microsoft.com/ja-jp/library/bb773205(en-us,VS.85).aspx たぶん関係ないですが、pszDisplayNameが挿している先をZeroMemory()でクリアしておく…とか。 >上記の「既存フォルダを参照するコード」のみを使用した >プロジェクトをつくってみました。 ちなみに、VS2005でやってみましたが特にエラーなしでフォルダ選択ダイアログは表示されています。 >もとのソースがメモリリークしていたので、それを塞ぎました。 >そしてそのソースにあるコードを追加すると、起動するとすぐに >「Access Violation」が発生します。 どういうリークで、どのように修正したのでしょう? WinMain()やmain()に入る前に「Access Violation」が発生…ということでしょうか? グローバル変数のコンストラクタでなにやらやっていたりしませんか?

yuki7091
質問者

補足

御回答、ありがとうございます。 WinMain()やmain()は見つかりませんでした。 (MFCを利用しているのから、隠されてる??) 現在は、メモリリークの箇所は問題ないと思うのですが、 こんな感じです。 (スレッドがダイアログを作っているので、  ダイアログを消してから、スレッドを消してます。) void CXXXXXThread::PostNcDestroy() { //ダイアログ削除 if(m_pXXXXXDlg != NULL){  m_pXXXXXDlg->DestroyWindow();  delete m_pXXXXXDlg;  m_pXXXXXDlg = NULL; }  //スレッド削除  //WaitForSingleObject(this->m_hThread, INFINITE);//スレッド終了までずっと待つ  TerminateThread(this->m_hThread, 0xffffffff);//スレッド強制終了  delete this; } 先に公開したソースのみでプロジェクトでも Violationがはっせいしているので、 SHBrowseForFolderの使い方に問題がありそうです。 調べてみると、初期化しなくてはいけない、と他サイトで ありましたが、本件に関係あるのでしょうか。

回答No.5

私も、windows畑ではないので分かりません。 直接・本当の問題点では無いと思いますが気になった点を一つ。 BROWSEINFO構造体のコールバック関数のポインタを入れるメンバ変数(bInfo.lpfn)についてです。 SHBrowseForFolderをインターネットで検索すると、上記メンバにダイアログのコールバック関数のアドレスがセットされています。 しかし提示されたコードを見るとNULLがセットされていますが、何か意図があるのでしょうか? WINDOWS側からコールバック関数を呼ぼうとしているが関数のアドレスがNULLのため、おかしくなっているのでは?

参考URL:
http://sunafukin.jp/dannatti/software/vc/control/chap8.html
yuki7091
質問者

補足

ご回答、ありがとうございます。 BROWSEINFO構造体のコールバック関数のポインタを入れるメンバ変数(bInfo.lpfn)は NULLでも問題なさそうですが、自信ありません。 (今回の場合、WEBにあったソースをそのまま転用してしまいました。) 今度は、ちがうPCで今回のソースを動かしてみました。 すると、Access Violationが発生しません。 ・Access Violationが発生する環境  ・WinXp pro(SP3)、VC++6.0 (SP6) ・Access Violationが発生しない環境  ・WinXp pro(SP2)、VC++6.0 (SP6)  ・WinXp home(SP2)、VC++6.0 (--) そして、現在まで確認できたことは、 1、以下を使用するとviolationが発生します。 ・SHBrowseForFolder ・SHFileOperation 2、起動時にviolationが発生します。  (上記のSHBrowseForFolderなどを使用する前に、発生します。)  起動後は問題なく動いていそうです。 すみませんが、よろしくお願いします。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.4

>コードを追加することによって、元ソースのエラーを誘発することは >あるのでしょうか。 あります。

yuki7091
質問者

お礼

「お礼」と「補足」の欄がが逆になりますが、お許し下さい。 上記の「既存フォルダを参照するコード」のみを使用した プロジェクトをつくってみました。 ※ダイアログ上に、上記コードを埋め込むボタン、  エディットボックス(CString m_csFolderName;)を用意しました。 すると、「 Access Violation」が発生しました。 発生箇所は、 pIDList = ::SHBrowseForFolder(&bInfo); から以降のようです。 これらから、何か分かりませんでしょうか。

yuki7091
質問者

補足

御回答、ありがとうございます。 そうですか、、、 ちなみに、ボタンを用意して、そのボタンに 既存フォルダを参照するコードを埋め込むと 「 Access Violation」が発生します。 ※某サイトを参考にしてつくっているので、問題ないように  思います。(動作も問題ありませんでした。) **************** void CAAAAAA::OnButtonSelectFolder() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください UpdateData(TRUE); BROWSEINFO bInfo; LPITEMIDLIST pIDList; TCHAR szDisplayName[MAX_PATH]; // BROWSEINFO構造体に値を設定 bInfo.hwndOwner = AfxGetMainWnd()->m_hWnd; // ダイアログの親ウインドウのハンドル bInfo.pidlRoot = NULL; // ルートフォルダを示すITEMIDLISTのポインタ (NULLの場合デスクトップフォルダが使われます) bInfo.pszDisplayName = szDisplayName; // 選択されたフォルダ名を受け取るバッファのポインタ bInfo.lpszTitle = _T("フォルダの選択"); // ツリービューの上部に表示される文字列 bInfo.ulFlags = BIF_RETURNONLYFSDIRS; // 表示されるフォルダの種類を示すフラグ bInfo.lpfn = NULL; // BrowseCallbackProc関数のポインタ bInfo.lParam = (LPARAM)0; // コールバック関数に渡す値 // フォルダ選択ダイアログを表示 pIDList = ::SHBrowseForFolder(&bInfo); if(pIDList == NULL){ // 戻り値がNULLの場合、フォルダが選択されずにダイアログが閉じられたことを意味します。 }else{ // ItemIDListをパス名に変換します if(!::SHGetPathFromIDList(pIDList, szDisplayName)){ // エラー処理 } // szDisplayNameに選択されたフォルダのパスが入っています m_csFolderName = szDisplayName; // 最後にpIDListのポイントしているメモリを開放します ::CoTaskMemFree( pIDList ); } UpdateData(FALSE);//データ初期化(反映) }

  • isle
  • ベストアンサー率51% (77/150)
回答No.3

「(NTDLL.DLL) にあります: 0xC0000005: Access Violation」でググって最初に表示されるページに書いてあったのですが、 プロジェクトの設定をシングルスレッドからマルチスレッドに変更すると良いらしいです。(未確認) プロジェクト→設定→C/C++タブ カテゴリをコード生成に変更 使用するランタイムライブラリ

yuki7091
質問者

補足

ご回答、ありがとうございます。 設定を確認すると、マルチスレッドになっていました。 (この設定が必要なことを知りませんでした。) やはりソースにミスがあるのでしょうか、、、

回答No.2

お疲れ様です。 参照URLに記載したアドレスを見ても問題解決の糸口が見えなかったでしょうか? おそらくはアクセスできないメモリにアクセスしています。 >> 一般的なバグの場合、 >> 元のソースでバグがなく、私がそのソースにコード加えた場合、 >> 私の加えたコードにバグが潜んでいると考えれますが、 >> 今回の「 Access Violation」の場合、 >> 元のソースで「 Access Violation」がなく、私がそのソース >> にコード加えた場合、 >> 私の加えたコードにその要因が潜んでいるのでしょうか。 変更前のソースをデバッグモードで動かして「Access Violation」が出なければ、貴方のプログラム変更に誤りがあると考えるのがほぼ正しいと思います。

参考URL:
http://msdn.microsoft.com/ja-jp/library/cc413691.aspx
yuki7091
質問者

補足

ご回答、ありがとうございます。 今回の経緯は、 もとのソースがメモリリークしていたので、それを塞ぎました。 そしてそのソースにあるコードを追加すると、起動するとすぐに 「Access Violation」が発生します。 そのコードが問題の原因と思って、別のコードを加えても 起動のするとすぐに「Access Violation」が発生します。 このように コードを追加することによって、元ソースのエラーを誘発することは あるのでしょうか。

回答No.1

お疲れ様です。 過去の質問を「Access Violation」で検索すると解決策が見えてくると思います。

参考URL:
http://oshiete1.goo.ne.jp/qa3030097.html
yuki7091
質問者

補足

ご回答、ありがとうございます。 検索しても、なかなか自分の思う回答が見つかりませんでした。 すみませんが、以下の私の認識は正しいかどうか、 判断して頂けませんでしょうか。 一般的なバグの場合、 元のソースでバグがなく、私がそのソースにコード加えた場合、 私の加えたコードにバグが潜んでいると考えれますが、 今回の「 Access Violation」の場合、 元のソースで「 Access Violation」がなく、私がそのソースにコード加えた場合、 私の加えたコードにその要因が潜んでいるのでしょうか。

関連するQ&A