この記事は、Linux で同じ名前のシンボルが競合する問題の解決策に関する関連情報を主に紹介します。必要な友人はそれを参照してください
Linux で同じ名前のシンボルが競合する問題の解決策
最近、仕事で次のような悲惨な状況に遭遇しました。 質問:
Linux には 3 つのモジュール aa、bb、および cc があります。 基本的な状況は次のとおりです。
cc はコンパイルされ、cc.so 動的ライブラリを取得するために接続されます。 cc には次の インターフェースがあります:
cc_fun { …… do();//调用名为do的cc模块内部函数 …… }
bb は bb.a static ライブラリを取得するためにコンパイルおよび接続されます。bb には次のインターフェースがあります:
bb_fun { …… handle = dlopen(cc.so, RTLD_LAZY);//加载cc.so pccfun = dlsym(handle, “cc_fun”);//获取cc_fun函数指针 (*pccfun)();//调用cc_fun函数,此时应该会调用cc模块中的do()函数 do();//调用名为do的bb模块内部函数(与cc模块中的do()函数同名,实现却不相同) …… }
aa コンパイル後、bb.a に接続します。 -lbb リンク オプションを使用して、aa 実行可能プログラムを取得し、インターフェイス関数 bb_fun( of bb.a ) を呼び出します。
main { …… bb_fun();//调用bb_fun函数 …… }
作業中に、aa が実行時に常に異常な動作をすることがわかりました。機能の異常を特定したところ、問題は同じ名前の do() 関数に集中していることがわかりました。出力の印刷により、プログラム内の do() 関数への 2 つの呼び出しが両方とも bb モジュールの do() 関数を呼び出しているのに対し、cc モジュールの do() 関数は一度も呼び出されず、その結果、異常が発生したことがわかりました。プログラムの動作とメモリ リーク。 何度も検証した結果、Linuxプログラムの各ライブラリのシンボルテーブルは、最終的にはプログラムが配置されているグローバルシンボルテーブルにロードされるため、このとき、同じ名前のシンボルが存在する場合のみ、最初にロードされたシンボルを呼び出すことができます。つまり、後でロードされた同じ名前のシンボルは、以前のシンボルによって上書きされます。 cc モジュールの do() 関数は bb モジュールの do() 関数によって上書きされるため、呼び出すことができません。
これ以上ナンセンスはありません。 。 。
多くの不満足な方法を試した結果、最終的な解決策は次のとおりです:1. -Wl,-Bsymbolic -Wl,--version-script,version 接続オプションを cc makefile に追加します。これは、バージョン内のスクリプトを意味します。ファイルは、エクスポートする関数を指定するために使用されます。
2.version ファイルの実装は次のとおりです。
VERS{ global: cc_fun; local: *; };
メイクファイルが存在するディレクトリにファイルを保存します。
3. 3 つのモジュールを再コンパイルして接続すると、問題は解決します。
以上がLinux での同じ名前のシンボル間の競合の解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。