生成中の出力ファイルタイプがどのようなタイプであっても、リンク編集中に結合されないウィークシンボルリファレンスにより、重大なエラー状態が発生します。
静的実行可能プログラムを生成中の場合は、シンボルは絶対シンボルに変換され、ゼロの値が割り当てられます。
動的実行可能プログラムまたは共有オブジェクトの作成中の場合は、シンボルは定義されていないウィークリファレンスとして残されます。プロセスの実行中に、実行時リンカーがこのシンボルを検索し、一致が検出されない場合は、重大な実行時再配置エラーを生成する代わりに、そのリファレンスをゼロのアドレスに結合します。
従来は、これらの定義されていないウィークリファレンスシンボルは、機能の存在をテストするためのメカニズムとして使用されていました。たとえば、次の C コードフラグは、共有オブジェクト libfoo.so.1 内で次のように使用されていました。
#pragma weak foo extern void foo(char *); void bar(char * path) { void (* fptr)(); if ((fptr = foo) != 0) (* fptr)(path); } |
アプリケーションがリファレンス libfoo.so.1 で構築されると、シンボル foo の定義が検出されたかどうかに関係なく、リンク編集は、正常に完了します。アプリケーションの実行中に、機能アドレスが非ゼロをテストすると、その機能が呼び出されます。ただし、シンボル定義が検出されない場合には、機能アドレスはゼロをテストするため、その機能は呼び出されません。
ただし、コンパイルシステムは、定義されないセマンティクスを保持しながら、このアドレスの比較テクニックを参照します。その結果、テストステートメントは最適化処理によって削除されます。さらに、実行時シンボルの結合メカニズムでは、このテクニックの使用にこれ以外の制限も加え、これにより、すべての動的オブジェクトが整合性のあるモデルを使用できる状態ではなくなります。
ユーザーは、この方法で定義されていないウィークリファレンスを使用することをやめ、その代わりに RTLD_DEFAULT フラグを指定した dlsym(3DL) を使用してシンボルの存在テストを行うことをお勧めします (「機能のテスト」を参照してください)。