【问题标题】:Link to the same DLL twice - Implicit and explicit at the same time两次链接到同一个 DLL - 同时隐式和显式
【发布时间】:2015-08-25 21:42:54
【问题描述】:

我正在处理的项目两次加载同一个库:

  1. 使用 LoadLibrary
  2. 使用 lib 文件和“__declspec(dllimport/dllexport)”静态加载 DLL。

在这种情况下发生了什么?这两个“加载”是使用相同的堆还是共享其他东西。例如。是否与两次调用 LoadLibrary 相同或相似?

我的一般问题是,当通过第二种方法从 exe 调用 dll 方法时,我遇到了堆栈损坏问题。我想知道问题是否可能是因为第一次加载?所有项目都使用相同的 RT、对齐等。

【问题讨论】:

  • LoadLibrary 并不总是加载库。相反,它可以增加已加载 DLL 的引用计数。
  • 此外,静态依赖项 (dllimport) 的加载发生在您有机会调用 LoadLibrary 之前(除非您使用延迟加载),因此您的数字与实际发生的顺序相反.
  • 您找到原因了吗(很可能在您的动态 dll/lib 导入系统中)?
  • 是的,我找到了根本原因,它与 DLL 加载无关。问题在于结构对齐错误。
  • 另见LoadLibrary Reference Counting。如果它是同一个 DLL,那么它只加载一次。额外的 LoadLibrary 调用会增加引用计数。

标签: visual-c++ dll static-linking dynamic-linking loadlibrary


【解决方案1】:

通过 “静态加载 DLL 与 lib 文件和 _declspec(dllimport/dllexport)” 我假设你的意思是你编译你的可执行文件与 .lib 为一个依赖项,并且在运行时 .dll 由 exe 自动加载(在开始时)。这是来自FreeLibrary (surprisingly) MSDN page的片段:

系统为每个加载的模块维护每个进程的引用计数。由于加载时动态链接而在进程初始化时加载的模块的引用计数为 1。每次调用 LoadLibrary 加载模块时,模块的引用计数都会增加。除非模块是第一次加载并且作为数据或图像文件加载,否则引用计数也会通过调用 LoadLibraryEx 增加。

换句话说,.dll 在应用程序启动时被加载(因为您链接到它)并且LoadLibrary 只是增加它的引用计数()。如需更多信息,您还可以查看DllMainthis dll guide

绝对没有理由在同一个应用程序中对同一个 .dll 使用这两种方法。

第二种方法是首选方法,if .dll 带有一个 .h 文件(保存由库,在编译时需要)和一个 .lib 文件(指示喜欢者将 .dll 文件中的引用添加到可执行文件中)。

另一方面,如果您只有 .dll 文件并且您以某种方式拥有它导出的函数的签名,则第一种方法是唯一的方法。在这种情况下,您必须在应用程序中定义指向这些函数的指针并使用GetProcAddress 对其进行初始化。在某些情况下,这种方法是首选的,例如,当 .dll 中的功能仅在程序流的角落情况下需要时,在这种情况下,没有必要链接到 .lib 文件并在应用启动时加载 .dll,如果假设在 99% 的情况下不需要它。此外,这种方法的一个主要优点是:如果 .dll 以某种方式被删除,那么只有与其相关的功能将不起作用(LoadLibrary 将失败),而使用另一种方法,应用程序不会启动。

现在,如果没有详细信息,我无法深入了解您遇到的这个具体问题。您说您“通常”调用一个函数(根据 .h 文件中的定义),它会失败,而如果您使用函数指针调用它(使用相同的参数)它会成功吗?堆栈错误信息是什么?

注意:根据我的经验,在这种情况下堆栈损坏的典型原因是 callercallee 之间的调用约定不匹配(stdcallcdecl 或反之亦然)。此外,混合 DebugRelease 可能会带来问题。

【讨论】:

    猜你喜欢
    • 2011-06-15
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多