初期化されたデータの複数のインスタンス (各インスタンスはシステムに固有) を同じオブジェクト内で提供できます。しかし、このようなデータは、関数インタフェースを介して提供する方法が簡単で、お勧めです。シンボル機能関数ファミリの作成を参照してください。実行可能ファイル内に初期化データの複数のインスタンスを提供するには、特別な配慮が必要です。
次の例では、foo.c 内のデータ項目 foo を初期化して、マシン名の文字列を指しています。このファイルはさまざまなマシン用にコンパイルでき、各インスタンスはマシン機能で特定されます。このデータ項目への参照は、ファイル bar.c の bar() から行われます。次に共有オブジェクト foobar.so.1 が、foo の 2 つの機能インスタンスと bar() を結合することで作成されます。
$ cat foo.c char *foo = MACHINE; $ cat bar.c #include <stdio.h> extern char *foo = MACHINE; void bar() { (void) printf("machine: %s\n", foo); } $ elfdump -H foobar.so.1 Capabilities Section: .SUNW_cap Symbol Capabilities: index tag value [1] CA_SUNW_ID sun4u [2] CA_SUNW_MACH sun4u Symbols: index value size type bind oth ver shndx name [1] 0x108d4 0x4 OBJT LOCL D 0 .data foo%sun4u Symbol Capabilities: index tag value [4] CA_SUNW_ID sun4v [5] CA_SUNW_MACH sun4v Symbols: index value size type bind oth ver shndx name [2] 0x108d8 0x4 OBJT LOCL D 0 .data foo%sun4v
アプリケーションは bar() を参照できます。実行時リンカーはベースとなるシステムに関連する foo のインスタンスに結合します。
$ uname -m sun4v $ main machine: sun4v
このコードが適切に動作するには、コードが位置独立になるようにコンパイルされる必要があります。共有可能なオブジェクト内のコードではこれは一般的です。位置独立のコードを参照してください。位置独立のデータ参照は間接参照であるため、実行時リンカーは必要な参照を検索して、データセグメントの要素を更新できます。データセグメントのこの再配置更新では、テキストセグメントが読み取り専用として保持されます。
しかし、実行可能ファイル内のコードは位置依存であることが一般的です。また、実行可能ファイル内のデータ参照はリンク編集時に結合されます。実行可能ファイル内では、実行時リンカーがシンボル機能ファミリから選択できるように、シンボル機能のデータ参照は、大域データ項目を介して解決されない状態のままである必要があります。前の例の bar.c にある bar() からの参照が位置依存コードとしてコンパイルされた場合、実行可能ファイルのテキストセグメントは実行時に再配置される必要があります。デフォルトでは、この状態は重大なリンク時エラーとなります。
$ cc -o main main.c bar.c foo.o foo.1.o foo.2.o ... warning: Text relocation remains referenced against symbol offset in file foo 0x0 bar.o foo 0x8 bar.o
このエラー状態を解決する 1 つの方法は、bar.c を位置独立としてコンパイルすることです。ただし、この方法を正常に動作させるには、シンボル機能データ項目への実行可能ファイル内からの参照をすべて位置独立でコンパイルする必要がある点に注意してください。
データはシンボル機能メカニズムを使用してアクセスできますが、データ項目をオブジェクトへの公開インタフェースの一部にすることは問題となる可能性があります。より柔軟な別のモデルは、シンボル機能関数に各データ項目をカプセル化することです。この関数が、データをアクセスするための唯一の手段を提供します。シンボル機能関数にデータを隠すことによって、データを静的に定義し、非公開のままに維持できるという重要なメリットが得られます。前の例は、シンボル機能関数を使用するようにコーディングできます。
$ cat foobar.c cat bar.c #include <stdio.h> static char *foo = MACHINE; void bar() { (void) printf("machine: %s\n", foo); } $ elfdump -H main Capabilities Section: .SUNW_cap Symbol Capabilities: index tag value [1] CA_SUNW_ID sun4u [2] CA_SUNW_MACH sun4u Symbols: index value size type bind oth ver shndx name [1] 0x1111c 0x1c FUNC LOCL D 0 .text bar%sun4u Symbol Capabilities: index tag value [4] CA_SUNW_ID sun4v [5] CA_SUNW_MACH sun4v Symbols: index value size type bind oth ver shndx name [2] 0x11138 0x1c FUNC LOCL D 0 .text bar%sun4v $ uname -m sun4v $ main machine: sun4v