理解g ++链接器故障

时间:2015-10-02 14:21:35

标签: c++ linux linker g++

给定一个静态库,您可以使用

进行检查
$nm libgtest.a

为什么以下版本无法找到符号?

g++ -ISomePathToGTest -lgtest SomeUnitTests.cpp

许多未定义的引用中的一个看起来像这样:

SomeUnitTests.cpp:(.text+0x28): undefined reference to `testing::InitGoogleTest(int*, char**)'

但我在上面的'nm'命令中有这些行:

000000000000ffca T _ZN7testing14InitGoogleTestEPiPPc
000000000000ffca T _ZN7testing14InitGoogleTestEPiPPw

根据nm的手册,'T'表示该系统位于我正在检查的库的文本部分。我确定它不会从其他任何地方挑选这个库,并且它正在使用该构建命令找到这个库。

像这样构建SomeUnitTests.cpp的对象:

g++ -c -ISomePathToGTest SomeUnitTests.cpp

使用nm检查它只显示以下条目,以便在InitGoogleTest上搜索:

U _ZN7testing14InitGoogleTestEPiPPc

那么,它们应该匹配吗?但是,关注链接器如何匹配符号而不是我正在使用gtest,为什么它会失败?

1 个答案:

答案 0 :(得分:3)

为了清晰起见,简化您的命令行:

g++ -ISomePathToGTest -lgtest SomeUnitTests.cpp

调用g++ tooldriver执行以下操作:

  1. 调用GNU C ++编译器cc1plusSomeUnitTests.cpp编译为 一个临时汇编语言文件,其命令行基本上类似于:

    cc1plus -ISomePathToGTest SomeUnitTests.cpp -o /tmp/aaaa.s

  2. 调用GNU汇编程序as汇总aaaa.s 临时目标文件,命令行基本上类似于:

    as -ISomePathToGTest -o /tmp/bbbb.o /tmp/aaaa.s

  3. 调用GNU链接器ld以将bbbb.o与指定链接 和默认库,命令行基本上像:

    ld -L/default/library/search/paths... -lgtest /tmp/bbbb.o -lstdc++ -lother -ldefault -llibraries...

  4. 在链接器命令行中,对象文件和指定库的排序 反映了相应的源文件和您指定的库中的库 原始命令行:因为对象文件和库的排序很重要 对于链接器,g++的工作假设你知道这一点,那就是 命令行表达你想要的顺序。

    目标文件和库的排序对链接器很重要,因为 它将搜索库以查找某些符号foo的定义 并且只有当它已经看到一些目标文件(或库)时才会生成 对foo的未定义引用;如果它在库中找到定义 那么它不会在以后的库中搜索它的其他定义。

    这样做的结果是必须在所有对象之后提及库 引用它的文件或未定义的引用将确保。在 链接器不会检查命令行libgtest的链接 在所有,因为到目前为止没有看到任何目标文件,也没有 要解决的未定义符号。目标文件/tmp/bbbb.o是 随后检查,其未定义的引用只能 获取后面的默认库中的定义,保留所有引用 libgest未解决的符号。

    现在,您可以看到为什么将-lgtest移至结尾的问题的答案 命令行"更改链接顺序"。这是因为是你的意思 要求:而不是库对象文件(失败),你要求对象文件库(成功)。

    这是the linker's commandline manual-l namespec的文档是相关项目。