Cor*_*ein 2 c++ linker static-libraries
这是一个相当简单的应用程序的设置,我无法正确链接.基本上是单个源文件main.cpp,带有静态库的目录libbreakpad_client.a,以及库中的标头breakpad.
$ ls .
main.cpp libs breakpad
$ ls libs
libbreakpad_client.a
Run Code Online (Sandbox Code Playgroud)
以下是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;
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译它时,链接器抱怨它无法找到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
Run Code Online (Sandbox Code Playgroud)
但是如果我们查看存在的符号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()
Run Code Online (Sandbox Code Playgroud)
那么为什么链接器抱怨这些是一个undefined reference?
编译器的标志顺序很重要.您需要在源文件名后面放置-l标志:
$ g++ -Ibreakpad/src -Llibs -o main main.cpp -lbreakpad_client
Run Code Online (Sandbox Code Playgroud)
它在您编写此选项的命令中有所不同; 链接器按照指定的顺序搜索和处理库和目标文件.因此,在文件之后但之前
foo.o -lz bar.o搜索库.如果引用函数,则可能无法加载这些函数.zfoo.obar.obar.oz
链接线的顺序很重要!当库出现在参数列表中时,只会搜索一次库。如果此时没有未解析的符号,则它们不会发生任何其他事情。将命令更改为
g++ -Ibreakpad/src -Llibs -o main main.cpp -lbreakpad_client
Run Code Online (Sandbox Code Playgroud)