【问题标题】:Mixing debug and release libraries: Windows vs Linux, static vs shared混合调试和发布库:Windows vs Linux,静态 vs 共享
【发布时间】:2019-09-09 17:36:38
【问题描述】:

afewtimes 已经有人问过这个问题,但我发现它总是指 Windows。这是有道理的,因为 MSVC 失败并出现以下错误:

错误 LNK2038:检测到“_ITERATOR_DEBUG_LEVEL”不匹配:值“0”与 main.obj 中的值“2”不匹配

在我看来,在 Linux 上,它不会在构建时失败。

答案提到构建类型之间存在不同的 C++ 运行时,并且在此类库之间不共享 CRT 资源。不过,我不清楚这种行为在 Linux/Windows 和共享/静态库中有何不同。

我想更好地理解这一点。问题可能是:

  1. Windows 和 Linux 有区别吗?
  2. 如果它也是 Linux 中未定义的行为,为什么它不会在构建时失败?
  3. 静态库和共享库有区别吗?
  4. 我的 Linux 包管理器是否下载所有开发包的调试版本?查看usr/lib/,我似乎无法同时找到发布和调试库...

【问题讨论】:

  • 如果_ITERATOR_DEBUG_LEVEL 不同,则问题从编译阶段开始,而不是链接/库阶段
  • 那句话的后果是什么?这是否意味着共享库不应该成为问题?
  • 对于 Windows,当调用 ITERATOR_DEBUG_LEVEL 时,编译器会从各种类(例如 STL 类)中添加/删除代码。因此,当您链接到不同的调试级别时,您可能会链接到同一类的两个或多个不同版本,因此会出现错误。
  • 对。所以错误是在编译时引发的,如果没有,它会在运行时导致未定义的行为,对吧?这意味着链接永远不是问题,静态库和共享库在 Windows 中都有这个问题。对吗?
  • 是的,如果模块之间的类内部结构发生了变化,将导致未定义的行为。

标签: c++ linux windows linker


【解决方案1】:

是的,Linux 和 Windows 是不同的。对于 Windows,我不能说太多,但是对于 Linux 工具链,我们并没有真正的拆分 Debug 与 Release 构建。

我们有几个选择:

  • 启用了哪些优化?
  • 是否应该发出调试符号?
  • 其他一些不太相关的东西。

构建工具链所指的“发布”或“调试”只是一组选项。例如,CMake 的最小尺寸发布版本使用-Os -DNDEBUG,而 CMake 的调试版本使用-g。发行版在打包内容时还会添加其他选项。

但是除了那些选项之外,ABI 是相同的,所以它们都是兼容的(除了特别标记的选项 [*] - 但那些不在典型构建中使用)。所以没关系。您可以混合使用“调试”或“发布”对象,它会起作用。

至于 4),许多发行版的做法是使用拆分调试符号构建。这意味着调试信息是在一个单独的文件中发出的,并且通常是独立打包的。例如:

ii  libc6:amd64       2.27-3ubuntu1  GNU C Library: Shared libraries
ii  libc6-dbg:amd64   2.27-3ubuntu1  GNU C Library: detached debugging symbols

通常不安装第二个软件包。我手动安装它以通过完整的调试信息逐步完成 libc6。


[*] 例如,查看GCC code generation options。您会看到那些生成不兼容对象的对象带有警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多