查找导致未定义引用错误的源代码行

Arv*_*ian 5 c++ linker gcc g++

迟早,当用C/C++编程时,每个人都将面临"未定义的引用错误".

通常这是由缺少的库引起的,并且大多数错误在几秒钟内通过链接缺少的库来修复.但是,例如,当使用具有单独文件的模板进行声明和实现时,可能会因"非预期"模板实例化而导致未定义的引用.不幸的是,我们现在获得的所有信息都是"未定义的引用错误"的实例,没有可能的原因提示,例如调用者的行号等.

我很好奇:有没有一种简单的方法来发现调用函数/模板的实际源代码行导致未定义的引用错误?

Bri*_*erg 5

正如我在回答这个问题时提到的,是否可以直接获取导致链接错误的行号取决于编译器是否发出了所有必要的信息。

首先,这些是我遇到的导致您所看到的行为的情况:

  • 编译器发出错误的调试信息(solaris studio 12.3 在某些情况下具有调试/优化功能)
  • 为超出范围的对象执行的析构函数
  • 编译器插入的代码:
    • 堆栈保护器
    • 消毒剂
    • 用于检测代码以进行调试或分析的其他工具

如果您遇到类似以下的链接错误,我建议的追踪方法可能会有所帮助:

asdf.o: In function `whatever':
asdf.o(.text+0x1238): undefined reference to `fdsa'
Run Code Online (Sandbox Code Playgroud)

...因为至少你有一个可以使用的地址。

第一次尝试addr2line

~ addr2line -e asdf.o 0x1238
# If it works, you'll get:
asdf.cc:N
# If it doesn't work, you'll get:
??:?
Run Code Online (Sandbox Code Playgroud)

如果失败,请尝试objdump

~ objdump --dwarf=decodedline asdf.o

asdf.o:     file format elf64-x86-64

Decoded dump of debug contents of section .debug_line:

CU: asdf.cc:
File name                           Line number     Starting address
asdf.cc                                       1               0x1234
asdf.cc                                       3               0x1254
asdf.cc                                       5               0x1274
Run Code Online (Sandbox Code Playgroud)

在我在这里给出的完全捏造的示例中,没有.debug_line对应于0x1238(链接器错误中的地址)的条目,因此它可能是编译器魔术(例如,由堆栈保护器或消毒器之类的东西添加的额外代码),或者希望它与第 1/3 行发生的情况有关,因为地址位于这两行之间。

如果这还不够让你继续:当我想要更多一点继续时,我做了以下事情:

  1. 插入链接标志以阻止其破坏以获得破坏的符号
  2. 重新编译目标文件,但让它生成程序集
  3. 在程序集中搜索损坏的符号

假设程序集注释得足够好,那么将缺少的符号+来自程序集的信息关联起来应该不会太难,objdump并且至少在代码行上进行修复以开始其余的搜索(假设您还有更多兔子) STL 中经常出现这样的情况)。