リンカーとライブラリ

共有可能性の最大化

「基本システム」で説明したように、共有オブジェクトのテキストセグメントだけがそれを使用するすべてのプロセスによって共有され、データセグメントは通常共有されません。共有オブジェクトを使用する各プロセスは、通常、そのデータセグメント全体の専用メモリーコピーをそのセグメント内に書き込まれるデータ項目として生成します。データセグメントを削減するにはテキストセグメントに書き込まれることがないデータ要素を移動するか、またはデータ項目を完全に削除します。

次の節では、データセグメントのサイズを削減するために使用できるいくつかのメカニズムについて説明します。

テキストへの読み取り専用データの移動

読み取り専用のデータ要素はすべて、テキストセグメントに移動する必要があります。これは、const 宣言を使用して達成できます。たとえば、次の文字列は、書き込み可能なデータセグメントの一部である .data セクションにあります。


char * rdstr = 'this is a read-only string';

これに対して、次の文字列は、テキストセグメント内にある読み取り専用データセクションである .rodata セクション内にあります。


const char * rdstr = 'this is a read-only string';

読み取り専用要素をテキストセグメントに移動することによるデータセグメントの削減は目的に沿うものですが、再配置を必要とするデータ要素を移動すると、逆効果になるおそれがあります。たとえば、次の文字列配列があるとします。


char * rdstrs[] = { "this is a read-only string",
                    "this is another read-only string" };

最初は、次の定義の方が良く思われるかもしれません。


const char * const rdstrs[] = { ..... };

これにより、文字列とこれらの文字列へのポインタ配列は、確実に .rodata セクションに置かれます。ただし、ユーザーがアドレス配列を読み取り専用と認識しても、実行時にはこれらのアドレスを再配置しなければなりません。したがって、この定義では再配置が作成されます。この定義は次のように表わします。


const char * rdstrs[] = { ..... };

これにより、配列文字列は読み取り専用のテキストセグメント内に保持されますが、配列ポインタは、再配置できる書き込み可能なデータセグメント内に保持されます。


注 -

コンパイラによっては、位置に依存しないコードを生成するときに、実行時再配置を起こして、このような項目を書き込み可能セグメントに置くことになる読み取り専用割り当てを検出できるものがあります (たとえば、.picdata)。


多重定義されたデータの短縮

多重定義されたデータを短縮すると、データを削減できます。同じエラーメッセージが複数回発生するプログラムの場合は、1 つの大域なデータを定義し、他のインスタンスすべてにこれを参照させると効率が良くなります。次に例を示します。


const char * Errmsg = "prog: error encountered: %d";

foo()
{
    ......
    (void) fprintf(stderr, Errmsg, error);
    ......

この種のデータ削減に適した対象は文字列です。共有オブジェクトでの文字列の使用は、strings(1) を使用して調べることができます。次に例を示します。


$ strings -10 libfoo.so.1 | sort | uniq -c | sort -rn  

上記のコードは、ファイル libfoo.so.1 内に、データ文字列のソートされたリストを生成します。このリスト内の各項目には、文字列の出現回数を示す接頭辞が付いています。

自動変数の使用

データ項目用の常時記憶領域は、関連する機能が自動 (スタック) 変数を使用するように設計できる場合、完全に削除することができます。常時記憶領域を少しでも削除すると、通常これに対応して、必要な実行時再配置の数も減ります。

バッファーの動的割り当て

大きなデータバッファーは、通常、常時記憶領域を使用して定義するのではなく、動的に割り当てる必要があります。これにより、アプリケーションの現在の呼び出しで必要なバッファーだけが割り当てられるため、メモリー全体を節約できます。動的割り当てを行うと、互換性に影響を与えることなくバッファーのサイズを変更できるため、柔軟性も増します。