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

このQ&Aのポイント
  • ベースアドレスの設定方法や注意点について解説します。
  • 複数の同時に使用されるdllを作成する場合のベースアドレスの重なり回避方法について説明します。
  • モジュールの高速化のためにベースアドレスを指定する方法について考えます。
回答を見る
  • ベストアンサー

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

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

noname#113783
noname#113783

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

  • ベストアンサー
  • ttega
  • ベストアンサー率52% (9/17)
回答No.1

一応 MS 推奨のベースアドレスというのがあります。昔 MSDN で見かけた情報なのですが、今調べても見つけられませんでした。確か rebase のツールの説明あたりから辿れたような気がしたのですが・・・。 大まかに言えば DLL のファイル名の先頭の文字で分類して、A-D は 0x60000000, E-G は 0x61000000 といった具合で 0x69000000 くらいまで使用していたと思います。もちろん、ご自分の DLL に lib1.dll, lib2.dll があれば、lib1 と lib2 がかぶらないように調節してください。 ちなみに、どんなモジュールが配置されるかは確かに分かりませんが、自分のプロセスに関して言えば OS の DLL(こいつらはベースアドレスが決まっています)と自分が使用している DLL だけを気にすれば十分です。というか、他に IME の DLL とかもロードされますが、そこまで含めてコントロールするのは現実的には難しいでしょう。 それから、使用するアドレス空間を算出するには EXE ファイルの構造を知らないといけませんが、実用上は rebase したときにその DLL がどこからどこまでを使用したかが表示されるので、次の DLL のベースアドレスはその後ろに持ってくるだけでオーケーです。 高速化についてのご質問は意図がよく分からないのでパスで。ロード時間がある程度かかるのが許容できるなら、別にロード時に再配置されたって構わないような気がしますが?

noname#113783
質問者

お礼

>>OS の DLL(こいつらはベースアドレスが決まっています)と自分が使用している DLL だけを気にすれば十分 >>次の DLL のベースアドレスはその後ろに持ってくるだけでオーケー 単純にならべるだけでOKなんですね!(64kbで区切るんでしたっけ) 高速化についてはちょっと勘違いしていたので忘れてください。 回答ありがとうございました!

関連するQ&A

  • VC2005のDLL明示的リンク

    VC2005のDLL明示的リンクについて質問です。 <前提> DLLファイルに宣言されている関数(Export関数)が、 4ファンクションあるとします。そのDLLファイルを、 Dependency Walkerで確認すると、以下のようになります。 --------------------------- 関数名 エントリポイント --------------------------- add1 0x00001010 sub2 0x00001030 mul3 0x00001060 div4 0x00001090 <質問> このDLLファイルがexeファイルからLoadLibraryで 読み込まれた場合、プロセスメモリ上には、 上記のエントリポイントの順番で必ず配置されるのでしょうか? 補足ですが、この時、プロセスメモリ上にロードされる位置 は、気にしていません(ベースアドレスは変わることがあるのは認識しています)。 要は、エントリポイントの順番が変わったりしないかを、知りたいです。 <プロセスメモリ上に、エントリポイント順に配置されたイメージ> 0000_0000h --------------------------- (略) --------------------------- add1 --------------------------- sub2 --------------------------- mul3 --------------------------- div4 --------------------------- (略) --------------------------- FFFF_FFFFh <プロセスメモリ上に、エントリポイント順に配置されなかったイメージ> 0000_0000h --------------------------- (略) --------------------------- sub2 --------------------------- add1 --------------------------- div4 --------------------------- mul3 --------------------------- (略) --------------------------- FFFF_FFFFh それとも、こんな感じで、OS依存(実行環境依存)で、色々な配置に なるのでしょうか?

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

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

  • インデックスアドレス指定方式とベースアドレス指定方式の違い

    アドレス指定方式(アドレシング)についての質問です。 タイトルの通り、インデックスアドレス指定方式とベースアドレス指定方式の違いを教えていただきたいです。 参考書などでは、 ●インデックスアドレス指定方式 ・命令の番地部とインデックスレジスタの値を加算した値を有効アドレスとする ・インデックスレジスタの内容を変えるだけで別なアドレスの内容が参照できる ●ベースアドレス指定方式 ・命令の番地部が指定するアドレスに、ベースレジスタの内容を加算した値を有効アドレスとする ・ベースレジスタの値を変えるだけでプログラムが主記憶装置のどこからでも実行できる(再配置可能) となっています。 有効アドレス=番地部のアドレス+レジスタの値 となるのが同じで、基準となる値がインデックスアドレス指定方式のほうでは命令の番地部であり、ベースアドレス指定方式のほうはベースレジスタの値、ということまではわかったのですが、この「基準」が違うことでどういう違いがあるのか、具体的にどういう場合にどちらの方式が使われるのかがわかりません。 ベースアドレス指定方式の「再配置可能」という部分もどういう仕組みなのか、よくわからないです。 ご回答、よろしくお願いいたします。

  • VMEモジュールのベースアドレス

    コンピュータバス規格のひとつであるVMEバスを使用する必要性が あるのですが、身近に質問できる人間がいないので ここで質問させてください。 VMEモジュールにアクセスするには、 ベースアドレスを設定する必要があると思うのですが、 これはどのようにすればいいものなのでしょうか。 マニュアルを読むと、基板にあるスイッチを操作して、 それに対応するアドレスをプログラムで入力してやればいいと思うのですが、 スイッチとアドレスの具体的な対応がわかりません。 使いたいモジュールは64ch AMT-VME、 参考にしたサイトは http://hepwww.rl.ac.uk/Atlas-SCT/vme_addresses/vme_addresses.html http://atlas.kek.jp/tdc/AMT-VME/index.htmlです。

  • access2003参照設定の質問

    WinXP Aceess2003で作成したプロジェクトをWin7でコンパイル・実行などを行い、再び自分のXP に持帰ったら、"DLL読み込み時のエラーです"などのメッセージで動きません。 プロジェクトが壊れたと思い、新規作成したプロジェクトにインポートしようとしたら、"既存のモジュール、プロジェクト、オブジェクトライブラリと名前が競合しています"で別プロジェクトにもインポート出来ません。 色々見てみると、参照設定に"参照不可 Excel14.0 Oblect Library"があったので、チェックをはずしてOKをすると、これも"DLL読み込み時のエラーです"が出ます。 Win7で実行した時に、環境が変わったようですが、どうすれば良いですか? 宜しくお願い致します。

  • DLLをメモリに常駐する設定とした場合、DLLのメモリからの解放はどれくらいの期間で実現されるか

    Windows XP 高速化について。DLLをメモリに常駐する設定とした場合(Windows XPのレジストリ設定)、DLLの再利用がどれくらいの期間なかった場合、メモリから解放されるのでしょうか? 十分メモリがある場合は、どこまでも解放されず、DLLはメモリに常駐されっぱなしになるのでしょうか?それとも一定時間再利用がなければ解放になるのでしょうか?

  • Windowsでのfork方法

    Windowsプログラムで、UNIXライクなマルチプロセス処理を書きたいのですが、 fork()が使えないようで、代替の方法がわかりません。 CreateProcess()というAPIはありますが、これは単に実行モジュールの呼び出し を行う関数で、UNIXのようなfork()でプロセスを分けるものでは ないようです。 子プロセス内部で、構築済みのDLLを複数ロードしたいのですが、 そのDLLはマルチスレッド対応になっていないため、 マルチスレッド処理はできません。 具体的にやりたいと思っていることをプログラム的に書くと、 およそ以下のような処理です。(UNIXでよくやる手法です) ----- 実行処理のメイン() {  int p_pid[128];  for(int i=0; i<10; i++) {   switch(pid[i]=fork()){    case 0: // 子プロセスとしての処理     子プロセスが呼び出す関数();     exit(0);    case -1:     break;    default:     break;   }  } } void 子プロセスが呼び出す関数() {  LoadLiblary() と GetProcAddress() で、DLLを動的にロードし、  DLL内のAPIを呼び出す。  DLLがマルチスレッド対応でなくても、この関数は各々が別プロセスとして  複数同時実行されるので、問題なく処理できるはず。 } ----- この処理は、Windowsでは無理なのでしょうか? もしできるなら、Windowsで用意されているランタイムライブラリかAPIを 教えていただけないでしょうか? よろしくお願いします。

  • DLLはアドレスを共有する?

     CでWindowsプログラミングの勉強をしています.そこでDLLについての質問なのですが,ある本で「DLLは複数のプログラムが共有し,ひとつのDLLはひとつしかメモリ上に配置されない」という文章を読みました.プログラムはDLLの配置されてあるアドレスを元に,DLL内の関数を実行するのだと考えれば納得はいきましたが,よく考えたらおかしいと思いました.  それは「変数,関数」の取り扱いはどうなるのか,ということです.C言語で物理メモリアドレスを見る方法がわからないので何とも言えませんが,試しに,DLL内に次のような関数MyFunctionを用意し,このDLLを取り込むプログラムを同時に2つ走らせ,MyFunctionを何度も呼んでDll1_Variableの値を増加させていきました. LIBSPEC int MyFunction(LPCWSTR str) { static int Dll1_Variable=0; Dll1_Variable++; _tprintf(_T("%d\n"),Dll1_Variable); return 0; }  もしDLLが共有されているのならば,Dll1_Variableの値は2つのプログラムから同時に更新されると思うのですが,実際には2つのプログラム上でまったく独立(つまり各プログラムごとに1,2,3,...というように)増加していきました.こうなるとDLLって本当に共有されているのかという,不信感が出てきてしまいます.  なんだか重大な勘違いをしている気がしてなりませんが,上記のプログラムがなぜ独立に変数が増加していくのか,「DLLが共有される」というのは実際にはどういう仕組みになっているのか,ご存知の方がいらっしゃったらご教授ください.わかりにくい質問ですみません.よろしくお願いします.

  • 指定した実行中プロセスの、指定したメモリアドレスの値を読み取るにはどうしたらよいのでしょうか?

     指定した実行中プロセスの指定したメモリアドレスの値を読み取るにはどうしたらよいのでしょうか。  例えば(あくまで例えば)グーグルアースの実行中、現在センターに来ている座標をVBで取得したい場合などです。その座標が格納されているメモリアドレスはわかっているのですが、VBからそこへの手の出し方が判らないのです。 できれば一定時間ごとにその値を取得して表示したいと思っているのですが、VBからプロセスを指定したりそのメモリの値を見るなんて方法がさっぱり判らなくて困っています。

  • VBのメモリのアドレス取得

    C++で作成したDLLをVBから変数を渡して 文字列が格納されているメモリアドレスを取得して、 別のDLLにメモリアドレスを渡したいのですが、 具体的な指定の仕方を教えてください。