【问题标题】:Are there general guidelines for solving undefined reference/unresolved symbol issues?是否有解决未定义参考/未解决符号问题的一般准则?
【发布时间】:2010-10-04 06:14:49
【问题描述】:

我在工作的地方遇到了几个“未定义的引用”(链接期间)和“未解析的符号”(dlopen 之后的运行时)问题。这是一个相当大的makefile系统。

是否有链接库和使用编译器标志/选项来规避此类错误的一般规则和指南?

【问题讨论】:

    标签: c++ reference undefined symbols


    【解决方案1】:

    如果您使用的是 MSVC:

    您不能通过设置标志来规避此类错误:这意味着某些单元 (.cpp) 没有'已声明标识符的定义。这肯定是由于某处缺少包含或缺少对象定义(通常是静态对象)造成的。

    在开发过程中,您可以遵循这些指南(来自 those articles),以确保您的所有 cpp 都包含他们需要的所有标头,但仅此而已:

    • 每个 cpp 文件首先包含自己的头文件。这是最 重要的指导方针;其他一切 从这里开始。唯一的例外 到这个规则是预编译头 包含在 Visual Studio 中;那些 总是必须是第一个包含在 文件。更多关于预编译 本文第二部分的标题。
    • 头文件必须包含解析它所需的所有头文件。 这与第一个齐头并进 指导方针。我知道有些人试图 永远不要在其中包含头文件 声称效率的头文件或 类似的东西。然而, 如果一个文件必须在 头文件可以解析,它必须 被包含在某处。优势 将其直接包含在标题中 文件是我们总是可以决定 拉入我们感兴趣的头文件 并且我们保证它会 按原样工作。我们不必玩 “猜猜你需要什么其他标题” 游戏。
    • 一个头文件应该有最少数量的头文件 有必要解析它。以前的 规则说你应该拥有所有 在头文件中包含您需要的内容。 这条规则说你不应该有任何 超过你必须的。很明显,开始 通过删除(或不添加 第一名)无用的包括 陈述。然后,使用尽可能多的转发 尽可能声明,而不是 包括。如果你只有 类的引用或指针,你 不需要包括那个类' 头文件;前向参考将 做得更好,效率更高。

    但正如评论者所建议的,您似乎正在使用 g++...

    【讨论】:

    • 从所述问题来看,他有链接排序问题。这不是 .ccp->.o 问题。这是 -lA -lB 与 -lB -lA。更改头文件不会有任何区别。除非他从未定义过“未定义/未解析”元素,否则更改代码将无济于事。
    • 可怕> 哎呀!固定的。 mrree> 我不知道,但在阅读了您的回答后,我知道这是一个 g++ 特定问题(或 makefile 系统问题)?我更习惯于 MSVC 编译器,并且也可能发生完全相同的错误,所以也许我误解了,因为它们具有相同的 desc?
    • 也许吧。我不熟悉 MSVC 编译器错误。但是当他提到“在链接期间”和“在 dlopen 之后的运行时”时,我认为这是库的常见错误排序。见:stackoverflow.com/questions/492374/…
    • 我明白了,那么我应该补充一点,如果是在 MSVC 的情况下,这是我的答案。 Micheal 在问题中添加精确度后,我将立即删除此答案。
    【解决方案2】:

    建立一个 X 依赖于 Y 而依赖于 Z 的构建系统会有所帮助。当你进入圈子(Z 取决于 X)时,事情就会变得丑陋。

    通常是订单库被链接(“-lZ -lY -lX”与“-lX -lY -lZ”)导致悲伤。更罕见的是,您在搜索路径的多个位置有相同的库名称,或者链接到尚未重新编译的过时版本。

    "nm --demangle" 可以让您查看定义/使用事物的位置。

    "ldd" 可用于查看您依赖的动态库。

    gcc/g++ 标志 -print-file-name=LIBRARY 可以帮助准确追踪正在使用的库。


    事后思考:(因为您询问规则/指南。)

    可以设置一个 makefile 系统:

    • 如果 module=D 依赖于模块 A、B 和 C。
    • 然后尝试制作 module=D 将首先制作模块 A、B 和 C。
    • 而且,更重要的是,module=D 会自动确定其库(-lA 等)、库路径 (-LA) 以及来自模块 A、B 和 C 的 makefile 的包含路径 (-IA)。李>

    设置起来可能有点麻烦。上次我这样做时,我倾向于只缓存信息而不是分叉过多的 make 子进程。再加上 makefile-importing 和一个小的 perl 脚本来删除重复项。克鲁奇,我知道。 (那些不想花时间在基础设施上的权力。)但这是可以做到的。

    再一次,我使用的是 GNU-make,它有一些扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-12
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 2021-03-28
      • 2014-05-05
      • 1970-01-01
      相关资源
      最近更新 更多