DLLのしくみについて

[戻る]
とよ 2009/12/04(金) 17:00:38
 「VC2005 MFC」でソフト開発をしているものです。
VCの質問とはかけ離れた内容ですが、よろしくお願いします。

 DLLのしくみについて勉強していると、DLLのリンクの仕方には、

・実行してみて、本当に必要になるまでリンクを行わない方式
・実行直後の時点でリンクしてしまう方式

の2種類あり、ビルドの時点ではリンクされないことから、

・DLLは複数のプログラムから共有が可能

で、ハードディスク的にもメモリ的にも無駄なく効率的に使用できるとのことですが、
実行時にリンクするだけで、実行ファイルと共にDLLもメモリ展開されるのならば、メ
モリ的にはスタティックリンクするのと同じサイズになるのではないでしょうか?
 それともDLL内の関数がコールされたときに、DLLファイルをオープンし、その関数
の部分のコードだけメモリ展開し、ファイルをクローズするのでしょうか?もしそう
なら時間がかかりそうだな〜などと考えてしまいます。
 実際はどのような動きをしているのかが知りたいです。よろしくお願いします。


 

aetos 2009/12/04(金) 17:32:43
> メモリ的にはスタティックリンクするのと同じサイズになるのではないでしょうか?

たとえば、A.exe が B.dll、C.dll、D.dll をリンクしているとします。
そして、B 〜 D の各 DLL がそれぞれ X.dll をリンクしているとしたら…
A.exe を実行したときに、B 〜 D と X の DLL がそれぞれ1回ずつメモリに読み込まれ
ます。
もし、B 〜 D の各 DLL が X.DLL 相当のコードをスタティックリンクしていたら、
X.DLL 相当のコードは、同じものが3回読み込まれますよね。
もっとも、B 〜 D の各 DLL も A にスタティックリンクしてしまえば同じでしょうけ
ど。

複数のプロセスで共有できるのかどうかはよくわかりません。
どなたか詳しい方がいらっしゃったらご教示願えませんか。

ディスクの節約については、最近はディスクが大きく安くなっていることから、あまり
重要視されていません。
それよりも、アプリケーションに必要なバージョンを確実に使うために、同じ DLL の複
数のバージョンが共存できる仕組みを作ったりしています。
詳しくは「DLL Hell」で調べてみてください。

> それともDLL内の関数がコールされたときに、DLLファイルをオープンし、その関数
> の部分のコードだけメモリ展開し、ファイルをクローズするのでしょうか?

これは明らかに違います。

bun 2009/12/04(金) 17:47:11
DLLでメモリ節約できるのは以下のような場合です。

A.exe -+
 ↓    |
B.dll -+--> C.dll

このように、
A.exe, B.dll ともに C.dllを読み込んで使用する場合、
C.dllは1つ(1インスタンス)しかロードされません。

スタティックリンクなら、A.exe, B.dll双方に展開されるから
メモリ節約になるのは分かりますよね。

bun 2009/12/04(金) 17:50:29
補足です。

ハードディスクに対しては、

A.exe -+
       |
B.exe -+--> C.dll

となっている場合を考えればよいです。

スタティックリンクなら、A.exe, B.exe双方に取り込まれるので
ディスク領域の節約になるのは分かりますよね。

とよ 2009/12/04(金) 18:27:34
 aetosさん、bunさん、回答ありがとうございます。

 1つのプロセスでの動作の場合しか考えていませんでした。複数のプロセスを実行
した時は明らかにメモリ節約ですよね。ちょっと考えれば分かりそうなものなのに
なかなか想像力が乏しいですね・・・。
 自分で振っときながら何ですが、複数のプロセスで共有できるのというのは、

A.exe  B.exe
     ↓
    C.dll

というような場合のことですよね?DLL内の関数をA.exe、B.exeが同時に呼び出した場合
どうなるんですかね?例えば、

1. DLL内の関数a()をA.exeでコールする。
2. a()内の処理中にタスク制御がB.exeに飛び、B.exeからa()がコールされる。

 複数のプロセスが、上記のような動作をする場合は、a()の変数が破壊されたりしない
のかな・・・。そもそも「2.」のような動作をするかどうかの知識もないですが。少し勉強
してみます。ありがとうございました。

とよ 2009/12/04(金) 18:31:07
[[解決]]
 チェック忘れました。また違う疑問が出てきてますが、本題については理解できま
した。aetosさん、bunさん、ありがとうございました。

maru 2009/12/04(金) 18:44:53
> 複数のプロセスが、上記のような動作をする場合は、a()の変数が破壊されたりしな> のかな・・・。
データメモリはA.exeとB.exeそれぞれ別プロセスですので、問題ありません。
同じファイルをアクセスしていたら問題ですが。

maru 2009/12/04(金) 18:54:27
っていうか、関数の実行中にその関数を呼び出すと元の関数の変数が破壊されるんじ
ゃ、再帰呼び出しなんか不可能じゃん。
まあ、心配しているのはDLLのグローバル変数のことなんだろうけど。

仲澤@失業者 2009/12/07(月) 09:55:02
> 「VC2005 MFC」でソフト開発をしているものです。

う〜む。MFCもDLLなんですけどね(・・・Static Linkもできるけど)。
何だと思って使っていたのかが、気になるところです(vv;)。

maru 2009/12/07(月) 11:04:36
> う〜む。MFCもDLLなんですけどね(・・・Static Linkもできるけど)。
それを言ったらWindowsそのものもDLLの塊なんですけどね。

スレ主のとよさんが混乱するといけないから、
> 自分で振っときながら何ですが、複数のプロセスで共有できるのというのは、
について説明すると、共有してるのはコードメモリ、つまり命令が乗るメモリで
あって、実行の対象となるデータメモリは元のプロセス、つまりa.exeやb.exeに
属します。従って呼び出しが重複した場合であっても変数が壊れる心配は有りま
せん。

もっとも、関数がグローバルメモリを使用してたりして再投入可能(リエントラ
ント)になっていない場合、関数実行中にその関数を実行したら、正しい結果は
得られない可能性があります。
その可能性は複数のプロセスから呼び出した時ではなく、同一プロセスでもあり
得ます。

とよ 2009/12/11(金) 11:24:04
> う〜む。MFCもDLLなんですけどね(・・・Static Linkもできるけど)。
> 何だと思って使っていたのかが、気になるところです(vv;)。

 MFCもDLLで動いていることは知っていますが、そもそもそのDLLのどのように動いて
いるのかが分からないという感じでした。

> > 自分で振っときながら何ですが、複数のプロセスで共有できるのというのは、
> について説明すると、共有してるのはコードメモリ、つまり命令が乗るメモリで
> あって、実行の対象となるデータメモリは元のプロセス、つまりa.exeやb.exeに
> 属します。従って呼び出しが重複した場合であっても変数が壊れる心配は有りま
> せん。

 何となく、DLL呼び出しでの動作がイメージできました。まだまだ勉強すること
ばかりです。
 ありがとうございました。

古いスレッドには追加発言できません。