質問

C C ++ または C#。彼らは何であり、正確に何を話しているのか、そして彼らは何をリンクしているのですか?

役に立ちましたか?

解決

(ほとんどの場合、解釈されたコードを割り引く)ソースコード(記述内容)から実行可能コード(実行内容)に到達するには2つの段階があります。

1つ目は、ソースコードをオブジェクトモジュールに変換するコンパイルです。

2番目のリンクは、オブジェクトモジュールを結合して実行可能ファイルを形成するものです。

とりわけ、ソースコード(データベースアクセス、ネットワーク通信、グラフィカルユーザーインターフェイス用のライブラリなど)を表示せずにサードパーティライブラリを実行可能ファイルに含めることや、異なる言語(Cおよびアセンブリコードなど)を使用して、それらをすべて一緒にリンクします。

ファイルを実行可能ファイルに静的にリンクすると、そのファイルの内容がリンク時に含まれます。つまり、ファイルの内容は、実行する実行可能ファイルに物理的に挿入されます。

動的にリンクすると、リンクされているファイルへのポインター(たとえば、ファイルのファイル名)が実行可能ファイルに含まれ、そのファイルの内容はリンクに含まれません時間。これらの動的にリンクされたファイルが購入されるのは、後で実行可能ファイルを実行したときだけであり、ディスク上のファイルではなく、実行可能ファイルのメモリ内コピーのみに購入されます。

これは基本的に遅延リンクの方法です。さらに遅延したメソッド(一部のシステムでは遅延バインディングと呼ばれます)があり、動的にリンクされたファイルを、実際にその中の関数を呼び出そうとするまで持ち込みません。

統計的にリンクされたファイルは、リンク時に実行可能ファイルに「ロック」されるため、変更されることはありません。実行可能ファイルによって参照される動的にリンクされたファイルは、ディスク上のファイルを置き換えるだけで変更できます。

これにより、コードを再リンクすることなく機能を更新できます。ローダーは、実行するたびに再リンクします。

これは良い点と悪い点の両方です-一方で、より簡単な更新とバグ修正が可能になり、一方で、更新に互換性がない場合にプログラムが動作しなくなる可能性があります-これは恐ろしい「DLL地獄」の原因になることがあります;動的にリンクされたライブラリを互換性のないライブラリに置き換えると、アプリケーションが破損する可能性があると言及している人もいます(これを行う開発者は、追い詰められ、ひどく処罰されることを期待すべきです)


として、ユーザーが main.c ファイルを静的および動的リンク用にコンパイルする場合を見てみましょう。

Phase     Static                    Dynamic
--------  ----------------------    ------------------------
          +---------+               +---------+
          | main.c  |               | main.c  |
          +---------+               +---------+
Compile........|.........................|...................
          +---------+ +---------+   +---------+ +--------+
          | main.o  | | crtlib  |   | main.o  | | crtimp |
          +---------+ +---------+   +---------+ +--------+
Link...........|..........|..............|...........|.......
               |          |              +-----------+
               |          |              |
          +---------+     |         +---------+ +--------+
          |  main   |-----+         |  main   | | crtdll |
          +---------+               +---------+ +--------+
Load/Run.......|.........................|..........|........
          +---------+               +---------+     |
          | main in |               | main in |-----+
          | memory  |               | memory  |
          +---------+               +---------+

静的なケースでは、メインプログラムとCランタイムライブラリがリンク時に(開発者によって)リンクされていることがわかります。ユーザーは通常、実行可能ファイルを再リンクできないため、ライブラリの動作にこだわっています。

動的な場合、メインプログラムはCランタイムインポートライブラリ(動的ライブラリにあるものを宣言するが、実際には定義しないもの)にリンクされます。これにより、実際のコードが欠落していても、リンカーはリンクできます。

次に、実行時に、オペレーティングシステムローダーがメインプログラムとCランタイムDLL(ダイナミックリンクライブラリ、共有ライブラリ、またはその他の命名法)との遅いリンクを行います。

Cランタイムの所有者は、いつでも新しいDLLをドロップインして、更新またはバグ修正を提供できます。前述のように、これには長所と短所の両方があります。

他のヒント

この質問に対する適切な答えは、リンクが であるものを説明するべきだと思います。

(たとえば)Cコードをコンパイルすると、機械語に変換されます。実行時に、プロセッサがメモリを読み取り、メモリに書き込み、その種のものを追加、減算、比較、「ジャンプ」するバイトシーケンス。このようなものはオブジェクト(.o)ファイルに保存されます。

今、昔、コンピューター科学者はこの「サブルーチン」を発明しました。事。ここでコードとリターンのチャンクを実行します。最も有用なサブルーチンを特別な場所に保存し、それらを必要とするプログラムで使用できることに気づくまで、それほど長くはかかりませんでした。

初期の頃、プログラマーはこれらのサブルーチンが配置されていたメモリアドレスをパンチする必要がありました。 CALL 0x5A62 のようなもの。これらのメモリアドレスを変更する必要がある場合、これは退屈で問題がありました。

したがって、プロセスは自動化されました。 printf()を呼び出すプログラムを作成しますが、コンパイラは printf のメモリアドレスを知りません。そのため、コンパイラは単に CALL 0x0000 を書き込み、「この0x0000を printf "のメモリ位置に置き換える必要がある」というメモをオブジェクトファイルに追加します。

静的リンケージとは、リンカープログラム(GNUのものは ld と呼ばれる)が printf のマシンコードを直接実行可能ファイルに追加し、0x0000を printf のアドレスに変更します。これは、実行可能ファイルが作成されたときに発生します。

動的リンケージは、上記のステップが発生しないことを意味します。実行可能ファイル still には、「0x000をprintfのメモリ位置に置き換える必要があります」というメモがあります。オペレーティングシステムのローダーは、printfコードを見つけてメモリにロードし、CALLアドレスを修正する必要があります。プログラムが実行されるたびに

プログラムは、静的にリンクされる関数(通常、 printf などの標準ライブラリ関数は静的にリンクされる)および動的にリンクされる他の関数を呼び出すのが一般的です。静的なものは「部分になる」実行可能ファイルと動的なものの「参加」実行可能ファイルが実行されるとき。

両方の方法には長所と短所があり、オペレーティングシステムには違いがあります。しかし、あなたが尋ねなかったので、ここでこれを終了します。

統計的にリンクされたライブラリは、コンパイル時にリンクされます。動的にリンクされたライブラリは、実行時にロードされます。静的リンクは、ライブラリビットを実行可能ファイルに焼き付けます。ダイナミックリンクは、ライブラリへの参照をベイク処理するだけです。動的ライブラリのビットは他の場所に存在し、後で交換できます。

上記の投稿はどれも静的にリンクする方法を実際に示していることはないため、あなたが正しくそれを行ったことを確認して、この問題に対処します:

単純なCプログラム

#include <stdio.h>

int main(void)
{
    printf("This is a string\n");
    return 0;
}

Cプログラムを動的にリンクする

gcc simpleprog.c -o simpleprog

そして、バイナリで file を実行します:

file simpleprog 

そして、次の行に沿って何かが動的にリンクされていることを示します:

&quot; simpleprog:ELF 64ビットLSB実行可能ファイル、x86-64、バージョン1(SYSV)、動的リンク(共有ライブラリを使用)、GNU / Linux 2.6.26、BuildID [sha1] = 0xf715572611a8b04f686809d90d1c0d75c6028f0f、ストリップなし&quot;

代わりに、今回はプログラムを静的にリンクします:

gcc simpleprog.c -static -o simpleprog

この静的にリンクされたバイナリでファイルを実行すると、次のように表示されます。

strace ./simpleprog

&quot; simpleprog:ELF 64ビットLSB実行可能ファイル、x86-64、バージョン1(GNU / Linux)、静的にリンク、GNU / Linux 2.6.26、BuildID [sha1] = 0x8c0b12250801c5a7c7434647b7dc65a644d6132b、削除なし

そして、静的にリンクされていることがわかります。ただし、残念ながら、すべてのライブラリがこの方法で静的にリンクするのは簡単ではないため、 libtool を使用するか、オブジェクトコードとCライブラリを手動でリンクするのに長時間かかる場合があります。

幸運なことに、 musl のような多くの組み込みCライブラリは、ほとんどすべてのではないにしてもライブラリに静的リンクオプションを提供します。

作成したバイナリを strace すると、プログラムが開始する前にライブラリにアクセスしていないことがわかります。

<*>

動的にリンクされたプログラムの strace の出力と比較すると、静的にリンクされたバージョンのstraceがはるかに短いことがわかります!

(C#はわかりませんが、VM言語の静的リンクの概念があるのは興味深いです)

動的リンクには、プログラムからの参照のみがある必要な機能を見つける方法を知ることが含まれます。言語ランタイムまたはOSは、参照に一致するファイルシステム、ネットワーク、またはコンパイル済みコードキャッシュ上のコードの一部を検索し、いくつかの手段を講じて、メモリ内のプログラムイメージに再配置などを統合します。これらはすべて実行時に行われます。これは、手動またはコンパイラーで実行できます。混乱するリスク(つまり、DLL地獄)で更新する機能があります。

静的リンクはコンパイル時に行われ、すべての機能部分がどこにあるかをコンパイラーに伝え、それらを統合するよう指示します。検索、あいまいさ、再コンパイルなしで更新する機能はありません。すべての依存関係は、プログラムイメージと物理的に1つです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top