私はかなり大きなC++共有オブジェクトライブラリを書いていますが、デバッグが苦痛になる小さな問題に遭遇しました:
ヘッダーファイルで関数/メソッドを定義し、そのスタブを作成するのを忘れた場合(開発中)、実行可能ファイルではなく共有オブジェクトライブラリとしてビルドしているため、コンパイル時にエラーが表示されませんその機能を実装するのを忘れました。何かがおかしいとわかる唯一の方法は、実行時に、最終的にこのライブラリにリンクするアプリケーションが「未定義のシンボル」エラーで倒れるときです。
コンパイル時に必要なすべてのシンボル、おそらくMakefileに追加できるものがあるかどうかを確認する簡単な方法を探しています。
私が思いついた解決策の1つは、コンパイル済みライブラリをnm -C -U
すべての未定義参照のデマングル化されたリストを取得します。問題は、これがGLibCなどの他のライブラリ内にあるすべての参照のリストにもなることです。もちろん、最終的なアプリケーションが組み立てられると、このライブラリとともにリンクされます。すべてのヘッダーファイルでnm
からgrep
への出力を使用し、対応する名前のいずれかを確認することは可能ですが、これは異常なようです。確かにこれは珍しい問題ではなく、それを解決するより良い方法がありますか?
リンカオプション-z defs
/--no-undefined
を確認してください。共有オブジェクトを作成するとき、未解決のシンボルがあるとリンクが失敗します。
Gccを使用してリンカーを呼び出す場合、コンパイラー-Wl
オプションを使用して、オプションをリンカーに渡します。
gcc -shared ... -Wl,-z,defs
例として、次のファイルを検討してください。
#include <stdio.h>
void forgot_to_define(FILE *fp);
void doit(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (fp != NULL)
{
forgot_to_define(fp);
fclose(fp);
}
}
さて、それを共有オブジェクトに組み込むと、成功します:
> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded
ただし、-z defs
を追加すると、リンクは失敗し、不足しているシンボルについて通知されます。
> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed
Linux(使用しているように見える)ldd -r a.out
では、探している答えを正確に提供する必要があります。
更新:確認するa.out
を作成する簡単な方法:
echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so
ldd -r ./a.out
テストスイートはどうですか?必要なシンボルにリンクする模擬実行可能ファイルを作成します。リンクに失敗した場合、ライブラリインターフェイスが不完全であることを意味します。
一度同じ問題がありました。私はC++でコンポーネントモデルを開発していましたが、もちろん、コンポーネントは実行時に動的にロードする必要があります。 3つのソリューションが思い浮かびますが、それが私が適用したものです。
お役に立てば幸いです。