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

时间:2013-05-30 12:44:36

标签: c++ gcc linker g++

在使用C / C ++进行编程时,每个人都会遇到“未定义的引用错误”。

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

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

1 个答案:

答案 0 :(得分:3)

正如我在回答this question时提到的那样,是否直接获取导致链接错误的行号取决于编译器是否发出了所有必要的信息。

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

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

如果您的链接错误类似,我建议跟踪它可能会有所帮助:

asdf.o: In function `whatever':
asdf.o(.text+0x1238): undefined reference to `fdsa'

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

首先,试试addr2line

~ addr2line -e asdf.o 0x1238
# If it works, you'll get:
asdf.cc:N
# If it doesn't work, you'll get:
??:?

如果失败,请尝试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

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

如果这还不足以让你继续下去:当我想再继续下去时,我做了以下事情:

  1. 插入一个链接标志以阻止它进行解码以获取受损的符号
  2. 重新编译目标文件,但让它生成程序集
  3. 在程序集中搜索损坏的符号
  4. 假设程序集注释得足够好,那么将objdump +程序集中的缺失符号+信息关联起来应该非常困难,至少可以修复代码行以启动其余部分你的搜索(假设你还有更多的兔子洞,就像STL一样)。