3

これは、適切にリンクできないこのかなり些細なアプリケーションのセットアップです。基本的には、単一のソース ファイルmain.cpp、静的ライブラリを含むディレクトリlibbreakpad_client.a、および .xml 内のライブラリのヘッダーですbreakpad

$ ls .
main.cpp libs breakpad
$ ls libs
libbreakpad_client.a

これは、Google Breakpad のドキュメントmain.cppからそのまま引用した のソースです。

#include "client/linux/handler/exception_handler.h"

void crash()
{
  volatile int* a = (int*)(NULL);
  *a = 1;
}

static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded)
{
  printf("Dump path: %s\n", descriptor.path());
  return succeeded;
}

int main()
{
    google_breakpad::MinidumpDescriptor descriptor("/tmp");
    google_breakpad::ExceptionHandler eh(descriptor, 0, dumpCallback, 0, true, -1);
    crash();
    return 0;
}

ExceptionHandlerしかし、コンパイルしようとすると、リンカはコンストラクタとデストラクタが見つからないと不平を言います。

$ g++ -Ibreakpad/src -lbreakpad_client -Llibs -o main main.cpp
/tmp/ccDDGnQk.o: In function `main':
main.cpp:(.text+0xed): undefined reference to `google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&, bool (*)(void*), bool (*)(google_breakpad::MinidumpDescriptor const&, void*, bool), void*, bool, int)'
main.cpp:(.text+0x106): undefined reference to `google_breakpad::ExceptionHandler::~ExceptionHandler()'
collect2: error: ld returned 1 exit status

しかし、 に存在するシンボルlibbreakpad_client.aを見ると、関数が正確に期待どおりに存在することがわかります。

$ nm -an libs/libbreakpad_client.a | c++filt | grep "ExceptionHandler("
000000000000076c T google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&, bool (*)(void*), bool (*)(google_breakpad::MinidumpDescriptor const&, void*, bool), void*, bool, int)
000000000000076c T google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&, bool (*)(void*), bool (*)(google_breakpad::MinidumpDescriptor const&, void*, bool), void*, bool, int)
0000000000000972 T google_breakpad::ExceptionHandler::~ExceptionHandler()
0000000000000972 T google_breakpad::ExceptionHandler::~ExceptionHandler()

では、なぜリンカはこれらがundefined reference.

4

2 に答える 2

7

コンパイラへのフラグの順序は重要です。ソースファイル名の-lにフラグを付ける必要があります。

$ g++ -Ibreakpad/src -Llibs -o main main.cpp -lbreakpad_client

GCCのドキュメントから:

コマンドのどこにこのオプションを記述するかによって違いが生じます。リンカーは、指定された順序でライブラリとオブジェクト ファイルを検索して処理します。したがって、foo.o -lz bar.oライブラリzは file の後、 のfoo.o前に検索されますbar.obar.oで関数を参照している場合z、それらの関数がロードされていない可能性があります。

于 2013-09-25T18:34:29.997 に答える
4

リンク行の順序が重要です。ライブラリは、引数リストに表示されるときに 1 回だけ検索されます。この時点で未解決のシンボルがなければ、それ以外には何も起こりません。コマンドを次のように変更します

g++ -Ibreakpad/src  -Llibs -o main main.cpp -lbreakpad_client
于 2013-09-25T18:37:06.570 に答える