【发布时间】:2010-10-04 06:14:49
【问题描述】:
我在工作的地方遇到了几个“未定义的引用”(链接期间)和“未解析的符号”(dlopen 之后的运行时)问题。这是一个相当大的makefile系统。
是否有链接库和使用编译器标志/选项来规避此类错误的一般规则和指南?
【问题讨论】:
标签: c++ reference undefined symbols
我在工作的地方遇到了几个“未定义的引用”(链接期间)和“未解析的符号”(dlopen 之后的运行时)问题。这是一个相当大的makefile系统。
是否有链接库和使用编译器标志/选项来规避此类错误的一般规则和指南?
【问题讨论】:
标签: c++ reference undefined symbols
您不能通过设置标志来规避此类错误:这意味着某些单元 (.cpp) 没有'已声明标识符的定义。这肯定是由于某处缺少包含或缺少对象定义(通常是静态对象)造成的。
在开发过程中,您可以遵循这些指南(来自 those articles),以确保您的所有 cpp 都包含他们需要的所有标头,但仅此而已:
- 每个 cpp 文件首先包含自己的头文件。这是最 重要的指导方针;其他一切 从这里开始。唯一的例外 到这个规则是预编译头 包含在 Visual Studio 中;那些 总是必须是第一个包含在 文件。更多关于预编译 本文第二部分的标题。
- 头文件必须包含解析它所需的所有头文件。 这与第一个齐头并进 指导方针。我知道有些人试图 永远不要在其中包含头文件 声称效率的头文件或 类似的东西。然而, 如果一个文件必须在 头文件可以解析,它必须 被包含在某处。优势 将其直接包含在标题中 文件是我们总是可以决定 拉入我们感兴趣的头文件 并且我们保证它会 按原样工作。我们不必玩 “猜猜你需要什么其他标题” 游戏。
- 一个头文件应该有最少数量的头文件 有必要解析它。以前的 规则说你应该拥有所有 在头文件中包含您需要的内容。 这条规则说你不应该有任何 超过你必须的。很明显,开始 通过删除(或不添加 第一名)无用的包括 陈述。然后,使用尽可能多的转发 尽可能声明,而不是 包括。如果你只有 类的引用或指针,你 不需要包括那个类' 头文件;前向参考将 做得更好,效率更高。
但正如评论者所建议的,您似乎正在使用 g++...
【讨论】:
建立一个 X 依赖于 Y 而依赖于 Z 的构建系统会有所帮助。当你进入圈子(Z 取决于 X)时,事情就会变得丑陋。
通常是订单库被链接(“-lZ -lY -lX”与“-lX -lY -lZ”)导致悲伤。更罕见的是,您在搜索路径的多个位置有相同的库名称,或者链接到尚未重新编译的过时版本。
"nm --demangle" 可以让您查看定义/使用事物的位置。
"ldd" 可用于查看您依赖的动态库。
gcc/g++ 标志 -print-file-name=LIBRARY 可以帮助准确追踪正在使用的库。
事后思考:(因为您询问规则/指南。)
可以设置一个 makefile 系统:
设置起来可能有点麻烦。上次我这样做时,我倾向于只缓存信息而不是分叉过多的 make 子进程。再加上 makefile-importing 和一个小的 perl 脚本来删除重复项。克鲁奇,我知道。 (那些不想花时间在基础设施上的权力。)但这是可以做到的。
再一次,我使用的是 GNU-make,它有一些扩展。
【讨论】: