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

C++ 查找导致未定义引用错误的源代码行,c++,gcc,linker,g++,C++,Gcc,Linker,G++,在C/C++中编程时,每个人迟早都会遇到“未定义的引用错误” 这通常是由于缺少库造成的,大多数错误都是通过链接缺少的库在几秒钟内修复的。 然而,例如,当使用带有单独文件的模板进行声明和实现时,可能会由于“非预期”模板实例化而得到未定义的引用。不幸的是,我们现在得到的所有信息都是“未定义的引用错误”的实例,没有可能的原因提示,例如呼叫者的行号等 我好奇的是: 有没有一种简单的方法可以发现调用函数/模板的实际源代码行导致未定义的引用错误?正如我在对的回答中提到的,获取导致链接错误的行号是否简单取决于

在C/C++中编程时,每个人迟早都会遇到“未定义的引用错误”

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

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

正如我在对的回答中提到的,获取导致链接错误的行号是否简单取决于编译器是否发出了所有必要的信息

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

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

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

asdf.o: In function `whatever':
asdf.o(.text+0x1238): undefined reference to `fdsa'
。。。因为至少你有一个工作地址

首先,尝试添加行:

~ 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经常出现的情况一样).

    它通常给出函数的名称,只要调用的函数合理地唯一,就可以使用
    grep-n
    获取行号。。。但是,如果您有400个名为
    size()
    的函数,这可能没有多大帮助……这不只是要求输入符号名称的问题吗?但我想这取决于你所说的神秘的“C/C++”是什么意思。只是
    grep
    未定义标识符的文件。只是说使用grep查找函数不是解决方案。作用域解析运算符可能被省略,导致成员函数未定义,makefile/project中可能未包含文件,可能未包含正确的编译器特定导出,可能遗漏了外部,或者链接项目可以是C++中引用的C代码,而C可能是从外部C中被忽略的。Grep可能找到了其中的一些,但它绝不会找到所有。并不是所有使用GCC的系统都有grep。这里真正的问题是关于疑难案例的疑难解答。这不仅仅是一个Demanling问题,例如,请参阅实例化模板,它可能是原始源代码中难以发现的符号。您可能会使用诸如grep或general“在文件中查找[XYZ]”之类的工具来发现错误。我只是好奇是否有办法让编译器/链接器工具链提示我进入正确的方向,而不是自己去做。也许这是不可能的,因为编译器和链接器工具和步骤是分开的,但理论上,工具链应该可以提供更多信息。