【问题标题】:Link dll to static library and load it into an application linked against the same static library将 dll 链接到静态库并将其加载到链接到同一个静态库的应用程序中
【发布时间】:2011-12-17 19:16:25
【问题描述】:

我正在创建一个应用程序,它支持在运行时动态加载的 dll 形式的模块。代码布局如下:

  • 核心 - 静态库

    这具有加载共享库并调用“创建”函数的机制,该函数返回一个新的模块对象(使用共享标头)。

  • 模块共享库(链接到核心静态库)

    这个模块使用共享的模块头,也使用核心库中的其他类(因此它与核心库链接)。它被构建为包含来自静态库的所有符号。

  • 测试应用程序可执行文件(链接到核心静态库)

我的行为变得古怪,似乎是零星的。它们总是以访问冲突而告终,但似乎我非常明确地设置的成员变量(整数)将在以后的函数中作为垃圾打印出来(我已经验证它们之前没有被删除)。这似乎只有在加载动态库时才会发生(即使我从不调用 create 函数)。

我的主要问题是,这里是否存在共享库中的符号与可执行文件中的符号冲突的危险(因为它们来自同一个静态库)并导致问题,即使它们来自完全相同的静态库图书馆?

【问题讨论】:

  • 我目前在 OS X 上看到了这个,但它也可以在 Linux (Ubuntu) 和 Windows 上编译。我现在将在 Linux 上尝试一下,看看是否发生了同样的事情。
  • 尝试在 valgrind 下运行您的程序以更好地诊断它。
  • 核心库是否使用了任何无法复制的东西,例如命名文件或设备?
  • 不,核心库是完全独立的。似乎问题在于我没有将核心库编译为与位置无关的代码。所有文件都有 -fPIC 参数,但静态库没有。这在 Linux 上导致了错误,但在 OS X 上却没有。我不完全理解这是如何导致我所看到的表现的,所以我现在暂缓回答我自己的问题,以防其他人愿意更好地解释它。 (另外,我正在等待确保我不再看到问题)。

标签: c++ linker shared-libraries static-libraries


【解决方案1】:

我不能说 Linux 和 OS X 的行为,但在 Windows 上,以下正是正在发生的事情。既然你说你也想在 Windows 上编译,这是相关的。

您遇到的问题是您实际上在核心中拥有所有内容的多个版本。每个模块和应用程序本身都有自己的核心副本,并且它们的变量共享。这包括 C 运行时,因此像跨模块边界的 new/delete 这样的事情充满了危险。

要验证这是怎么回事,创建一个简单的测试:将核心中的全局设置为您的测试应用程序中的一个值,然后从动态加载的代码尝试访问该全局看看你得到了什么。我敢打赌,你会看到你的店铺在全球不会被反映出来!

解决方案:

1) 使核心成为共享动态库。这可能适合您,也可能不适合您。

2) 在具备上述知识的情况下极其谨慎地操作;所有 CRT 和/或您自己的核心状态都不会被共享,因此您必须确保在模块边界的自己一侧分配/销毁事物。

我自己的应用程序的设计几乎与您的相同;即一个静态库,应用程序和模块都需要共享代码,然后动态加载应用程序核心加载的插件。

对于必须跨模块访问的所有共享核心状态,我所做的是每个模块在加载后所做的第一件事是将其“核心指针”设置为应用程序中核心库的实例化。这可确保所有模块都使用相同的数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多