リンカーが実行可能ファイルを作成しているときは、リンカーのデフォルトの動作は、シンボルを定義されないままにする必要がある適切なエラーメッセージを表示して、リンク編集を終了させることです。次のように、再配置可能オブジェクト内のシンボル「リファレンス」が、シンボル「定義」と絶対に一致しない場合に、シンボルは定義されないままの状態になります。
$ cat main.c extern int foo(); main() { return (foo()); } $ cc -o prog main.c Undefined first referenced symbol in file foo main.o ld: fatal: Symbol referencing errors. No output written to prog |
これと同様の方法で、共有オブジェクトが動的実行可能ファイルを作成するために使用されているときに、共有オブジェクト内のシンボルリファレンスが、シンボル定義と絶対に一致しない場合は、このシンボルリファレンスも未定義シンボルになります。
$ cat foo.c extern int bar; 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. No output written to prog |
上記の例のような場合に、未定義シンボルを許可するには、リンカーの -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. No output written to prog |
ここで、prog は、libbar.so への明示的なリファレンスを使用して構築されます。また、libbar.so には libfoo.so への依存性があるため、prog から libfoo.so への暗黙的なリファレンスが確立します。
main.c は、libfoo.so によって作成されたインタフェースへの特定のリファレンスを実行するため、prog は、実際に libfoo.so に依存性を持つことになります。ただし、生成される出力ファイル内に記録されるのは、明示的な共有オブジェクトの依存関係だけです。そのため、libbar.so の新しいバージョンが開発され、libfoo.so への依存性がなくなった場合、prog は実行に失敗します。
この理由から、このタイプのバインディングは重大であると考えられ、暗黙的な参照は、prog のリンク編集中にライブラリを直接参照することにより、明示的に実行される必要があります (この例で示した重大なエラーメッセージ内に必要なリファレンスのヒントがあります)。