1. ホーム
  2. c++

[解決済み] 共有ライブラリの未解決シンボルのチェックを簡単に?

2023-04-08 20:50:21

質問

私はかなり大きな 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