符号未找到AKA未定义的符号

时间:2011-04-29 07:12:34

标签: c++ c unix compilation

在UNIX上工作的大多数人经常会遇到这种恼人的错误。 有时候解决的时间会少一些,有时需要花费很多时间。

即使我经常面对这个问题,我需要一些好的文件或关于c / c ++中特定错误的文章

可能存在符号未找到/未定义符号错误的所有情况。

有人能帮助我知道这些情况是什么吗?

4 个答案:

答案 0 :(得分:3)

该错误与UNIX / Windows /任何其他操作系统无关,而是与语言本身有关。使用编译器提供的信息进行诊断实际上相当简单。通常他们会告诉你缺少什么符号以及有时使用它的地方。缺少符号的主要原因是:

  • 您已声明但从未定义
  • 您已定义它,但未将已编译的符号(目标文件/库)添加到链接器
  • 它是外部的,您忘记链接库,或者您链接的是无效版本,或者订单错误。

如果您打算来定义符号但与声明(声明为void foo( int, double );但未定义void foo( double, int ))匹配,则第一个有点棘手。与其他所有符号一样在这种情况下,编译器会告诉你它正在寻找的确切签名,确保你已经定义了那个符号,而不是那些接近或类似的东西,如果你使用不同的特殊角落情况在声明和定义中调用约定,因为它们在代码中看起来非常相似。

在库外部代码的情况下,复杂性在于识别需要链接的库以便添加该符号,并且来自lib的文档。请注意,对于静态库,链接器命令行中lib的顺序会影响结果。

为了帮助您找到实际定义的符号,您可以使用nm(gcc,这在unix系统中很常见)。所以基本上你可以针对你链接的目标文件/ lib运行nm并搜索链接器抱怨的符号。这将有助于在顺序产生差异的情况下(即符号在那里,但链接器跳过它)。

在运行时(感谢Matthieu M.指出它)你可能会遇到与动态库类似的问题,如果在LD_LIBRARY_PATH中找到了错误的库版本,你可能会得到一个没有必需的库符号

答案 1 :(得分:2)

虽然它们可以依赖于平台,但我对安德烈亚斯和大卫的一些观点有一些“更复杂”的例子:

  • 处理共享库(.so或者)并链接未导出的符号(Windows上的dllimport / dllexport和* nix上的GCC的可见性(“默认”))
  • 或类似:链接静态库,同时期望共享库,反之亦然。这个与Mathieu关于链接另一个意外版本的库的评论有点类似。
  • 创建纯虚拟类,而不是为至少一种方法提供实现(导致没有vtable可用)。
  • 实际上是一个更复杂的声明但不定义的情况:处理大型嵌套模板时可以获得的链接错误。找出大的错误消息可能很难找到未定义的内容。

答案 2 :(得分:1)

对于大多数情况,当您获得符号未找到/未定义符号或有时甚至是“重复符号”错误时,它们通常源于链接器无法在您尝试构建的项目中找到该符号的事实

最好的方法是查看生成的映射文件或作为编译器输出的符号表。它可能看起来像这样:

Symbols

这将允许您查看符号是否存在。此外,可能还有其他深奥的问题,例如编译器优化可能导致符号重复,尤其是内联汇编。这些是最难检测到的。

至于良好的资源和材料,我没有很多好的参考资料。当我当时回答问题时,大多数高级工程师实际上已经从他们自己的经验中学习。

但我确信这些论坛的存在可以帮助我们加快这种知识的获取。

希望它有所帮助:)

干杯!

答案 3 :(得分:1)

我假设您指的是链接器错误。这是我最喜欢的一个列表:

  • 您忘了告诉链接器有关依赖项(例如LIB文件)。
  • 你有一个带有静态数据成员的类,忘了初始化它(只有C ++)。
  • 您声明的功能不是纯粹虚拟的,而是忘记实现它。
  • 您忘记实现从另一个函数调用的函数(只有C,C ++会产生更容易找到的编译器错误)。
  • 您声明了一个外部变量并忘记初始化它。
  • 函数的声明与实现不匹配(只有C ++,C会接受它并且可能会死得很厉害)。
  • 您忘记实现从另一个函数声明和调用的函数。