在使用 C/C++ 编程时,迟早每个人都会面临“未定义的引用错误”。
这通常是由缺少库引起的,并且大多数错误通过链接缺少的库在几秒钟内得到修复。但是,例如,当使用具有单独文件的模板进行声明和实现时,可能会由于“意外”模板实例化而导致未定义的引用。不幸的是,我们现在得到的所有信息都是“未定义的引用错误”的一个实例,没有可能的原因提示,例如调用者的行号等。
我很好奇:有没有一种简单的方法来发现调用函数/模板导致未定义引用错误的实际源代码行?
正如我在对这个问题的回答中提到的,获取导致链接错误的行号是否简单取决于编译器是否发出了所有必要的信息。
首先,这些是我遇到的导致您看到的行为的案例:
如果您有类似以下的链接错误,我建议的跟踪它可能会有所帮助:
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 行发生的任何事情有关,因为地址位于这两行之间。
如果这还不足以让您继续:当我想继续进行时,我做了以下事情:
假设程序集的注释足够好,将缺少的符号 + 来自 + 程序集的信息关联起来应该不难,objdump
并且至少修复代码行以开始其余的搜索(假设你还有更多的兔子STL 经常出现的情况)。