Oracle® Solaris 11.2 リンカーとライブラリガイド

印刷ビューの終了

更新: 2014 年 7 月
 
 

未定義シンボル

すべての入力ファイルを読み取り、シンボル解決がすべて完了すると、リンカーは、シンボル定義に結合されていないシンボル参照の内部シンボルテーブルを検索します。これらのシンボル参照は、未定義シンボルと呼ばれます。未定義シンボルがリンク編集処理に及ぼす影響は、生成される出力ファイルのタイプや、シンボルのタイプによって異なります。

実行可能ファイルの作成

リンカーが実行可能出力ファイルを生成する際のデフォルト動作は、「未定義のままのシンボルが存在するかぎり、適切なエラーメッセージを出力して処理を終了する」というものです。次のように、再配置可能オブジェクト内のシンボル参照が、シンボル定義と絶対に一致しない場合に、シンボルは定義されないままの状態になります。

$ cat main.c
extern int foo();

int main()
{
        return (foo());
}
$ cc -o prog main.c
Undefined           first referenced
 symbol                 in file
foo                     main.o
ld: fatal: symbol referencing errors

同様に、共有オブジェクトを使って動的実行可能ファイルを作成する場合、未解決のままのシンボル定義が存在していると、未定義シンボルエラーが発生します。

$ cat foo.c
extern int bar;
int foo()
{
        return (bar);
}
$ cc -o libfoo.so -G -K pic foo.c
$ cc -o prog main.c -L. -lfoo
Undefined           first referenced
 symbol                 in file
bar                     ./libfoo.so
ld: fatal: symbol referencing errors

前の例のように未定義シンボルを許可するには、リンカーの –z nodefs オプションを使用して、デフォルトエラー条件を抑制します。


注 -  –z nodefs オプションを使用する場合は、注意が必要です。処理の実行中に使用できないシンボル参照が要求されると、重大な実行時再配置エラーが発生します。このエラーは、アプリケーションをはじめて実行およびテストした際に検出される場合があります。しかし、実行パスがより複雑であるとエラー状態の検出に時間がかかり、時間とコストが浪費される場合があります。

シンボルは、再配置可能オブジェクト内のシンボル参照が、暗黙の内に定義された共有オブジェクト内のシンボル定義に結合されている場合にも、未定義シンボルのままになる場合があります。たとえば、前の例で使用したファイル main.c および foo.c に次のように続く場合です。

$ cat bar.c
int bar = 1;
$ cc -o libbar.so -R. -G -K pic bar.c -L. -lfoo
$ ldd libbar.so
        libfoo.so =>     ./libfoo.so
$ cc -o prog main.c -L. -lbar
Undefined           first referenced
 symbol                 in file
foo                     main.o  (symbol belongs to implicit \
                        dependency ./libfoo.so)
ld: fatal: symbol referencing errors

prog は、libbar.so に対する明示的な参照を使用して構築されます。libbar.solibfoo.so に対する依存関係があります。したがって、libfoo.so への暗黙的参照が prog から確立されます。

main.c は、libfoo.so によって作成されたインタフェースへの特定の参照を実行するため、prog は、実際に libfoo.so に依存性を持つことになります。ただし、生成される出力ファイル内に記録されるのは、明示的な共有オブジェクトの依存関係だけです。そのため、libbar.so の新しいバージョンが開発され、libfoo.so への依存性がなくなった場合、prog は実行に失敗します。

このため、このタイプの結合は致命的とみなされます。暗黙的参照は、prog のリンク編集中に直接ライブラリを参照することで明示的に行います。この例で示した重大なエラーメッセージ内に必要な参照のヒントがあります。

共有オブジェクト出力ファイルの生成

リンカーが共有オブジェクト出力ファイルを生成する場合、未定義シンボルをリンク編集の後も残すことができます。このデフォルト動作により、共有オブジェクトが、依存関係として共有オブジェクトを定義する動的実行可能ファイルからシンボルをインポートできます。

リンカーの –z defs オプションを使用すると、未定義シンボルが残っていた場合に、強制的に致命的なエラーにすることができます。共有オブジェクトを作成するときには、このオプションの使用をお勧めします。アプリケーションからシンボルを参照する共有オブジェクトは、extern mapfile 指令でシンボルを定義するとともに、–z defs オプションを使用できます。SYMBOL_SCOPE/SYMBOL_VERSION 指令を参照してください。

自己完結型の共有オブジェクトは、外部シンボルへのすべての参照は指定された依存関係によって満たされ、最大の柔軟性が提供されます。この共有オブジェクトは、共有オブジェクトの必要条件を満たす依存関係を判別し確立する手間をユーザーにかけることなく、多数のユーザーによって使用されます。

ウィークシンボル

ウィークシンボルは歴史的に、割り込みを回避したり、オプション機能をテストしたりするために使用されてきました。ただし、近年のプログラミング環境ではウィークシンボルは脆弱で信頼性が低いことが経験によって示されており、使用は推奨されません。

ウィークシンボル別名はシステム共有オブジェクト内で頻繁に使用されてきました。その意図は、代替のインタフェース名を提供することであり、典型的には「_」文字が前に付いたシンボル名です。このエイリアス名は、アプリケーションがシンボル名の独自の実装をエクスポートすることによる割り込みの問題を回避するために、他のシステム共有オブジェクトから参照できます。現実的には、この手法は複雑すぎることが証明され、整合性を持たずに使用されていました。最近の Oracle Solaris バージョンでは、システムオブジェクト間の明示的な結合を直接結合によって確立します。Chapter 6, 直接結合を参照してください。

ウィークシンボル参照は、実行時でのインタフェースの存在をテストするためにしばしば使用されていました。この手法は、構築環境および実行環境に制限を設け、コンパイラ最適化によって回避できます。dlsym(3C)RTLD_DEFAULT または RTLD_PROBE ハンドルと一緒に使用することで、シンボルの存在をテストするための一貫性のある堅牢な手段が提供されます。機能のテストを参照してください。