代码之家  ›  专栏  ›  技术社区  ›  kreuzerkrieg

如何检查悬挂机构为什么需要一些符号?

  •  1
  • kreuzerkrieg  · 技术社区  · 6 年前

    这个问题很麻烦,让我们试试简短的版本: 通常当你失败的时候 unresolved symbol reference 这是相当海峡前进,在这里你调用的东西,链接器找不到。你只要给你的链接器提供一个库就行了。有时,当你把头撞在墙上,却不明白为什么链接器要在这里或那里使用这个符号时,它不会被调用,至少不会直接调用。是否有一个工具/链接器开关可以解释为什么它认为符号需要“这里”?

    最初的问题是: 这是所有关于静态链接。我有一个小的实用程序,几行代码,一对夫妇包括。与名为 lib1 . 让我们说 依赖于另一个库, lib2 ,自 使用符号 sym1 锂离子电池2 . 但是没有什么 这可能取决于 . 然而,前面提到的微小实用程序失败了,因为 . 第一个问题是为什么?因为,在公用事业中 符号1 使用 在实用程序中使用,为什么链接器首先要费心寻找这个符号?第二个问题,包含链有可能引入符号 符号1 锂离子电池2 ?

    0 回复  |  直到 6 年前
        1
  •  2
  •   Severin Pappadeux    6 年前

    很显然,我成功地回答了这个问题,没有看到代码和错误信息。是时候打开我的psi咨询了。

    关于Linux/ELF目标上的链接,重要的是要记住,链接器在尝试满足/解析符号时,正在合并(并复制到最终可执行文件)部分(aka segments)。通常,应用程序有.text(代码段)、.rodata(只读数据)段、.data(r/w初始化数据)段、.bss(未初始化数据)段等。因此,如果需要符号,例如,一个编译文件中的三个函数,则会选择文件的整个.text部分。如果未使用但存在于节函数中的函数调用其他内容,链接器将开始搜索要满足的“其他内容”,即使它与应用程序无关。

    另外,还有一些C++特定的东西:对于具有虚拟函数的类,编译器生成VTABLE,指针指向每个虚拟函数,并将该表移动到.RoDATA节。注意,那是什么 我们认为as代码实际上结束于(只读)数据部分。

    如果您只定义了一个虚拟函数,那么链接器很可能会抱怨错误消息,如

    /tmp/cc5YTcBb.o:(.rodata._ZTV3CL1[_ZTV3CL1]+0x18): undefined reference to `CL1::fnc2()
    

    这个故事的寓意是:把代码和数据分割成尽可能小的部分,你的链接原子。理想情况下,每个函数都进入自己的部分,以及一段初始化或r/o数据。

    一般来说,人们应该期望链接器使用更多的RAM,可能是较慢的链接阶段,但更小更快的应用程序。

    命令行使用,看一下GCC手册wrt选项的含义。

    g++ -fdata-sections -ffunction-sections -fipa-pta main.cpp -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed