dllのロードアドレスについて

このQ&Aのポイント
  • C++で作成したアプリケーションを起動すると、不正なdllの基底アドレスによるエラー終了が発生する
  • アプリケーションが実行時にロードするdllの基底アドレスが不正になる理由についての質問
  • dllがロードされる基底アドレスがどのように決まるかについての教授をお願いしたい
回答を見る
  • ベストアンサー

dllのロードアドレスについて

いつもお世話になっております。 現在、アプリケーションのデバッグを行っていて、dllのロードについて不明な点があります。 C++で作成したアプリケーションを起動すると、main関数が呼ばれる前に「アプリケーションが正しく初期化されませんでした(0xc0000005)。」というダイアログボックスが表示され、エラー終了してしまうという現象が発生しています。 但し、このアプリケーションは共通のソースを使用して、条件コンパイルによってGUIの描画部分等が違うといった、複数のアプリを作成することができます。そして、このうちの1つのアプリのみ上記のようなエラーが発生してしまいます。 デバッガによって正常に動くアプリとエラーになるアプリとで、アプリ実行時にロードされるdllの基底アドレスに違いがあるということが分かりました。 ※エラーになる方は、明らかに不正なアドレスにロードされているdllがあります。大抵のdllは0x60000000以降のアドレスですが、0x00300000代にロードされるdllがあります。 そこで、アプリケーションが実行時にロードするdllの基底アドレスが不正になってしまう理由がわかればと思い質問いたしました。 (コンパイル時のリンクオプション等が間違ってしまっているのかと思っています。。。) そもそも、dllがロードされる基底アドレスがどのように決まるものなのかも分からないのですが、どなたか御教授して頂けないでしょうか? 以上、よろしくお願いします。

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

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.5

MinGWは使用したことないので解決できる情報になるかは不明ですが… >kernel32.dllのiname関数(だと思いますが、、)から、mingwm10.dllにアクセスする際にエラーになっています。 >で、このmingwm10.dllがあやしいアドレス0x003d1000にロードされたdllになります。 Microsoftからシンボル情報をDLしてきたのでしょうか? 私のトコロには入れていないので何とも言えませんが…。 Dependency Walkerと、Visual Studioの呼び出し履歴からあたりを付ける手程度しか。 >ちなみにですが、exeを起動するとmain関数までの一連の流れをご存知でしたらご教授して頂け無いでしょうか? OS内部まで追っているわけではありませんので、先に書いた以上のことは不明です。 検索してみるとそういう情報の書かれたページがあるのではないかと思いますが。 スタートアップルーチンに関しては、ライブラリにもよると思われます。 # VS2005だと、C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\crt0.cに_tmainCRTStartup()とか書かれていますが…。 # これらの関数のあるアドレスがEXEなどのエントリポイントとしてリンクされているようです。

Pkakedashi
質問者

お礼

お礼が遅くなり申し訳ありません。 今回のエラーの調査よりも緊急の作業が入ってしまい、作業が頓挫してしまいました。まだ、未解決ではありますが、再開の目処がまだたたない為、一度締め切らせて頂きます。 何度も貴重なご意見ありがとうございました。

その他の回答 (4)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.4

>スタートアップルーチンとは、main関数のことでよろしいでしょうか? >mainまで呼ばれていないので、そこは大丈夫だとおもいます。 OSから起動されてからmain関数を呼ぶまでと、main関数から処理が戻された後の後始末の処理を行うのがスターアップルーチンです。 # C言語ならば、OSから渡されたコマンドラインパラメータをargcやargvに分割したり、環境変数ブロツクのアドレスを受け取ってmain関数に渡すたために準備したりなどなどのいろいろな処理を行う必要があります。 0xc0000005だと、アクセス違反っぽいですが、ポインタ関係とかでおかしかったりしませんか? 他のプログラムに組み込んだ場合は正しく初期化できていて、問題のプログラムに組み込んだ場合だと初期化の順番が正しくない…など。 デバッガから起動したらアクセス違反の発生した場所とか特定できませんか?

Pkakedashi
質問者

補足

ご回答ありがとうございます。 >OSから起動されてからmain関数を呼ぶまでと、main関数から処理が戻された後の後始末の処理を行うのがスターアップルーチンです。 勉強になります。 >デバッガから起動したらアクセス違反の発生した場所とか特定できませんか? kernel32.dllのiname関数(だと思いますが、、)から、mingwm10.dllにアクセスする際にエラーになっています。 で、このmingwm10.dllがあやしいアドレス0x003d1000にロードされたdllになります。 >OSから渡されたコマンドラインパラメータをargcやargvに分割したり、環境変数ブロツクのアドレスを受け取ってmain関数に渡すたために準備したりなどなどのいろいろな処理を行う必要があります。 ちなみにですが、exeを起動するとmain関数までの一連の流れをご存知でしたらご教授して頂け無いでしょうか?

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.3

>C++で作成したアプリケーションを起動すると、main関数が呼ばれる前に「アプリケーションが正しく初期化されませんでした(0xc0000005)。」というダイアログボックスが表示され、エラー終了してしまうという現象が発生しています。 >但し、このアプリケーションは共通のソースを使用して、条件コンパイルによってGUIの描画部分等が違うといった、複数のアプリを作成することができます。そして、このうちの1つのアプリのみ上記のようなエラーが発生してしまいます。 スタートアップルーチン、またはグローバル変数などに設定しているクラスのコンストラクタで死んでいるのではないでしょうか? あるクラスのコンストラクタを処理するためには、別のクラスのコンストラクタが完了している必要がある。とかそのような感じの。 >0x00300000代にロードされるdllがあります。 必ずしも不正とは限らないかと。 あまり使われることは無いでしょうけど。 Visual Studioでデフォルトのままだと、アプリケーションは0x00400000辺りから、DLLは0x01000000辺り…でしたか。 http://messiah-annex.at.webry.info/200501/article_7.html の下の方にDLLのロードアドレスについて記載されています。 ロードしようとしているアドレスが使用済みの場合はOSが別アドレスに変更します。 その結果、0x00300000に読み込まれたのかも知れません。

Pkakedashi
質問者

補足

ご回答ありがとうございます。 >スタートアップルーチン、またはグローバル変数などに設定しているクラスのコンストラクタで死んでいるのではないでしょうか? >あるクラスのコンストラクタを処理するためには、別のクラスのコンストラクタが完了している必要がある。とかそのような感じの。 スタートアップルーチンとは、main関数のことでよろしいでしょうか? mainまで呼ばれていないので、そこは大丈夫だとおもいます。 グローバル変数の初期化の可能性は有り得るかもしれませんが、現状は、アプリケーションのソースは正常に動くものと、一緒にしているのですが、同様のエラーが発生してしまいます。 (アプリケーション名(自作のdll含む)、ディレクトリの構成が現状違います。自作したdllは正常(だと思うところ)にロードされています。) >ロードしようとしているアドレスが使用済みの場合はOSが別アドレスに変更します。 >その結果、0x00300000に読み込まれたのかも知れません。 なるほど、ロードされたdllに問題というよりは、それ以前にエラー(?)が発生している可能性もあるのですね。確かに、確認したところ、通常ロードされるところに何かしらの値が入っていました。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

単に初期化方法が間違っているなどではないのでしょうか または想定していないデータがDLL渡されたため例外が発生しているとか エラー処理の手抜きしてある部分をたまたまつついてしまったとか そのDLL作者または提供元に問い合わせはしてみたのでしょうか

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.1

開発環境・実行環境は何でしょうか? VCなどであればDLLの読み込みは、 LoadLibraryなどの動的読み込みですか? >コンパイル時のリンクオプション等が間違ってしまっている この可能性は高そうですが、 今までは一度もこの様な現象は起こらなかったのでしょうか?

Pkakedashi
質問者

補足

ご回答ありがとうございます。 >開発環境・実行環境は何でしょうか? >VCなどであればDLLの読み込みは、 LoadLibraryなどの動的読み込みですか? 申し訳ありません。ちょっと省略してしまいました。 開発環境は、VCでは無く、MinGW3.1.0-1 + WideStudio397-4です。 ただ、ちょっと特殊なのですがmainは自分で作成し、WideStudioで作成したクラス等を呼ぶようなつくりになっています。 DLLの読み込みは、暗黙的リンクなので、アプリケーション起動時に自動で読み込まれます。 >今までは一度もこの様な現象は起こらなかったのでしょうか? はい、今まで作成していたものは、このような現象が発生しませんでした。

関連するQ&A

  • DLLの呼び出しについて

    C++BuilderXで開発したアプリで、CreateProcess()で子プロセスを呼び出すときに 時々、DLLの初期化エラー(0xc0000142)が発生するので、DependencyWalkerを使って 呼び出されているDLLを調べたところ、124個ものDLLが呼び出されていました。 中には"googledesktopcommon.dll"などまったく関係の無さそうなものまで呼び出されていました。 本来、呼び出されるDLLはプログラム内で使用されるものに限定されるものだと 思うのですが、アプリケーション実行時に呼び出されるDLLというのは どこで決まっているのでしょうか。 また、余計なDLLが呼び出されないように改善することはできますでしょうか。 宜しくお願いします。

  • DLLが LoadLibrary() でロードされたか判断できますか

    VC++6.0でDLLを作成しています。 アプリケーションが自分のDLLを LoadLibrary()でロードしたのか、 LIBリンクでロードしたのか、判断はできるでしょうか。 DLLの処理の中で、LoadLibrary()でロードされた場合と LIBリンクでロードされた場合の処理を分けたいのが目的です。 (LIBリンクの場合、デタッチ時にはメインのスレッドしか動作しないため) <補足> 正式にはどう呼ばれているか解らないのですが、「LIBリンク」は VCの設定でリンクするLIBを指定し、アプリケーションでは DLLが提供する関数名を記述する方法を意味します。

  • WNASPI32.DLLのロード

    Easy CD Creatorを使いたいです。 Easy CD Creatorの起動時に、WNASPI32.DLLがロードできませんでした(以下略) というエラーが出ます。 検索すると同様の症状は多く発生しているみたいです。 WNASPI32.DLLはシステムフォルダにあります。 WNASPI32.DLLがWNASPI32.DLLをロードするパスがシステムフォルダ以外なのか、WNASPI32.DLLのファイル自体に問題があるのかも解決のために知りたいです。 他にも役立ちそうな情報を教えてもらいたいです。

  • dllが見つからない

    PhysXLoader.dll が見つからなかったため、このアプリケーションを開始できませんでした。アプリケーションをインストールし直すとこの問題は解決される場合があります。 とアプリケーションを起動するとエラーが出ます コンパイル時はdllをきちんと指定され読み込まれているのですが、 どうすれば改善されるでしょうか? プログラムでは #pragma comment(lib,"PhysXLoader.lib") と指定しています

  • regsvr32 Shdocvw.dll で 失敗します

    windows Xp SP3 IE6 を使用していて、新しいウインドウが開かなかったり、固まったりするので イベントログをみたら エラー発生アプリケーション iexplore.exe、バージョン 6.0.2900.5512、エラー発生モジュール shdocvw.dll、バージョン 6.0.2900.5512、エラー発生アドレス 0x00034254 と表示されていました。 regsvr32 Shdocvw.dll をファイル名を指定して実行を行うと、 Shdocvw.dll の DllRegisterServer は失敗しました。 戻りコード 0x8002801cと表示が出ます。 regsvr32.exe /u Shdocvw.dll は成功します。その後の regsvr32.exe /i Shdocvw.dll は上記同様の失敗表示が発生します。 urlmon.dll Shdocvw.dll Actxprxy.dll Oleaut32.dll Mshtml.dll Browseui.dll Shell32.dllはそれぞれ成功します。 どなたか再インストールなしに復旧する方法をご教授願います。 よろしくお願いします。

  • VC++.NET DLLからのダイアログの表示

    こんばんは。 VC++.NETでDLLを作成しました。 内容はダイアログを表示させるだけの単純なもので DLLの種類はMFC拡張DLLで作成しました。 (CDIALOGを継承したクラスTESTDIALOGのコンストラクタ、デストラクタがあるだけのもの) これをテスト用の単純なMFCアプリケーションで呼び出したところ ダイアログを表示させることができましたが 別の複雑なアプリケーション(DLLからDLLを呼ぶなどしている)で 呼び出したところダイアログが表示されません。 コンパイルエラーなどもでないし 何がいけないのか分かりません。 呼び出し側ではメニューにイベントハンドラを作ってそこで TESTDIALOG dlg; dlg.DoModal(); としているだけなのですが・・・ (デバッガで追ったところMFCのdlgcore.cppのCDialog::DoModalの m_lpDialogTemplateNameが不適切なptrとなる辺りに原因はありそうなのですが何故そうなるのかわかりません。) どなたかダイアログが表示されない原因がお分かりになる方 よろしくお願いします。

  • ベースアドレスの設定について

    高速化の為に/BASEオプションや defファイルなどで dll やプロセスのベースアドレスを設定する場合についてですが、これはどういう風にアドレスを設定すればいいのでしょうか? 例えばプログラムや dll がメモリにロードされる時に、マルチプロセスな OS 用のアプリケーション等の場合だと他にどんなモジュールがメモリに配置されているかは実行時じゃないとわかりませんよね?こういう場合はベースアドレスは普通設定しないものなのでしょうか? それと、複数の同時に使用される可能性のある dll を作成する場合に、ベースアドレスを重ならないように設定するといいとのことですが、これは単純に "A.dll のベースアドレスに A.dll の大きさ(バイト)を足したものを B.dll のベースアドレスにする" みたいな感じでいいでしょうか? それからもう1つ、高速であるべきモジュールを作成する時に、どうしても再配置によるオーバーヘッドを払いたくない場合、初期化時に、ソースコード中のアドレスを指定している部分を実行時のベースアドレスとオフセットによって書き換える、ということをしたらいいんじゃないかと思ったのですが、こんなことをするのは現実的ではないですか?(ロード時間がある程度かかるのは気にしないとして) 1つでも回答いただけたら嬉しいです。よろしくお願いします。

  • dllが見つからないのですが・・・

    いつもお世話になります。 今回、VBで簡単なアプリケーションを作成しています。 そのなかで「a.dll」を使おうとしているのですが、「a.dllが見つかりません」とのエラーが出てしまいます。 現在、テストとしてwin2000で動かしています。このdllを"WINNT\system32"やこのアプリのあるディレクトリにコピーしてみたのですがそれでも見つからないのです。なにか原因があるのでしょうか?

  • DLL参照時に指定されたモジュールが見つかりません。(HRESULT からの例外 0x8007007E) が発生してしまう。

    C++プロジェクト(Windowsフォームアプリ)を作成し、あるサイトで公開されているDLLを実装し→コンパイル→デバッグ実行させた所、問題なく動作が確認できたのですが、 クラスライブラリで作成したC++新規プロジェクトに同じくDLLを実装し、同一ソリューション内にC#又はC++でWindowsフォームアプリを作成し、先に作成したクラスライブラリプロジェクトを参照させる形態で作成した際に、コンパイル→デバッグ実行させた所、コンパイルは通ったのですがデバッグ実行時に、DLLを参照しようとしたタイミングで 「DLL参照時に指定されたモジュールが見つかりません。(HRESULT からの例外 0x8007007E) が発生してしまう。」 というエラーが発生してしまいました。 何故Windowsフォームアプリ単体時にはDLLが参照できたのに、クラスライブラリにし複数プロジェクトにして実行するとエラーが発生してしまうのか、どなたか原因、解法等 心得ておられましたら御指南のほど宜しくお願いします。 以下 事象詳細です。 開発環境:Microsoft Visual Studio 2008 公開DLL:USB-IOを制御する目的のUSBIODLLDemo.dllというDLLです。 <成功時> 1.C++プロジェクト(Windowsフォームアプリ)新規作成 2.DLLがインストールされているフォルダから.dllファイル, .hファイル、.libファイルをコピーしプロジェクト新規作成したフォルダにコピーする 3.プロジェクトのプロパティ→構成プロパティ→リンカ→入力→追加の依存ファイル に.libファイル名を記入 4.ダウンロードの.hファイルから __declspec(dllimport) BYTE __stdcall GetNo(void); __declspec(dllimport) void __stdcall P1Write(BYTE newVal); __declspec(dllimport) BYTE __stdcall P1WriteBit(BYTE Bit, BOOL Tf01); __declspec(dllimport) BYTE __stdcall P1Read(void);  をコピーしstdafx.h へ貼付け。 5.stdafx.hへ貼り付けた宣言がこのままではコンパイルが通らなかったため #define BYTE unsigned char #define BOOL bool  を追記。 6.ダウンロードしたDLLの関数を使用した一文を実装 7.コンパイル→デバッグ実行→ 無事実行完了! <エラー発生時> *下記事象ではC#Winフォームアプリを挙げていますがC++Winフォームアプリで試しても同じ結果になりました。 1.C++プロジェクト(クラスライブラリ)新規作成 2.DLLがインストールされているフォルダから.dllファイル, .hファイル、.libファイルをコピーしプロジェクト新規作成したフォルダにコピーする 3.プロジェクトのプロパティ→構成プロパティ→リンカ→入力→追加の依存ファイル に.libファイル名を記入 4.ダウンロードの.hファイルから __declspec(dllimport) BYTE __stdcall GetNo(void); __declspec(dllimport) void __stdcall P1Write(BYTE newVal); __declspec(dllimport) BYTE __stdcall P1WriteBit(BYTE Bit, BOOL Tf01); __declspec(dllimport) BYTE __stdcall P1Read(void);  をコピーしStdafx.h へ貼付け。 5.Stdafx.hへ貼り付けた宣言がこのままではコンパイルが通らなかったため #define BYTE unsigned char #define BOOL bool  を追記。 6.ダウンロードしたDLLの関数を使用した一文を実装(公開関数として) 7.C#プロジェクト(Windowsフォームアプリ)新規追加 *C++(Windowsフォームアプリ)でやっても同じ結果になりました。 8.新しい参照の追加で上のクラスライブラリプロジェクトを追加 9.フォームアプリ側でクラスライブラリプロジェクトの関数を実行する処理を実装 clsTest ctst; ctst.Exec(); 10.コンパイル→デバッグ実行→DLLを参照しようとしたタイミングでエラー発生! 「DLL参照時に指定されたモジュールが見つかりません。(HRESULT からの例外 0x8007007E) が発生してしまう。」 *クラスライブラリ側の、DLLの関数を呼んでいる部分をコメントアウトするとエラー無く実行できてしまいます。

  • 【C++】DLLの中身

    親クラス:ParentClassが、 メンバ m_a メソッド GetA SetA それを継承した子クラス:ChildClass が、 メンバ m_a ←オーバーライド m_b ←子クラスで追加 メソッド GetA ←オーバーライド SetA ←オーバーライド GetB ←子クラスで追加 SetB ←子クラスで追加 という構成で、それぞれ別のDLLを作成したとき、 以下のどちらになるでしょうか? 「(1)」の認識であり、必ず、子クラスは、親クラスのファイルサイズよりも大きくなるという認識です。 (1)「ChildClass.DLL」では、 コンパイル時の「ParentClass」の処理内容を内包している。 (※ChildClass.DLLのコンパイル時に、親クラスの処理も、記載されたような状態でDLLが作成される) (2) 「ChildClass.DLL」では、 コンパイル時の「ParentClass」の処理内容を内包せず、 実行時に、親クラスのDLLに委譲している。 また、「(1)」であるならば、 親クラスにバグがあって修正した場合、 必ず子クラスも再コンパイルしなければならない認識ですが合っていますでしょうか? /**************************************/ また、DLLがクラスX、クラスYで構成されているとき、 クラスXのobj と、 クラスYのobj と、 クラスXのlib (クラスYから、クラスXの処理を呼び出せるようにするために、クラスX側からpublic で実行できる関数のIN・OUTの仕様が記載されている) クラスYのlib が、含まれているという認識で良いのでしょうか? .   コンパイル時、libや、objができますが、これらはDLLに内包される