将dll链接到静态库并将其加载到链接到同一静态库的应用程序中

时间:2011-12-17 19:16:25

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

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

  • 核心 - 静态库

    这有一种加载共享库并调用“create”函数的机制,该函数返回一个新的Module对象(使用共享头)。

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

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

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

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

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

1 个答案:

答案 0 :(得分:5)

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

您遇到的问题是您实际拥有核心内所有内容的多个版本。每个模块和应用程序本身都有自己的核心副本,其变量共享。这包括C运行时,因此跨模块边界的新/删除等事情充满了危险。

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

解决方案:

1)使核心成为共享动态库。这可能是您的选择,也可能不是。

2)根据上述知识进行极其谨慎的操作;所有CRT和/或您自己的核心状态都不会被共享,因此您必须确保在模块边界的其他方面分配/销毁事物。

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

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