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