链接到同一个DLL两次 - 同时隐式和显式

时间:2015-08-25 21:42:55

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

我正在工作的项目,加载相同的库两次:

  1. with LoadLibrary
  2. 使用lib文件和“__declspec(dllimport / dllexport)”静态加载DLL。
  3. 在这种情况下发生了什么?这两个“加载”是否使用相同的堆或共享其他内容。例如。是否与调用LoadLibrary两次相同或相似?

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

1 个答案:

答案 0 :(得分:3)

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

  

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

换句话说, .dll 在应用程序启动时加载(因为你链接了它),而LoadLibrary只增加了它的引用计数()。有关详情,您还可以查看DllMainthis dll guide

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

第二种方法是首选方法,如果 .dll 附带 .h 文件(其中包含导出的函数定义)编译时需要的库)和 .lib 文件(指示liker将 .dll 文件中的引用添加到可执行文件中)。

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

现在,如果没有详细信息,我无法深入了解您遇到的特定问题。你说你正常地调用一个函数(来自 .h 文件中的定义),如果你使用函数指针调用它(使用相同的参数)它会成功,它会失败吗?什么是堆栈错误消息?

注意:根据我的经验,像这样的场景中堆栈损坏的典型原因是调用调用者被调用者之间的约定不匹配( stdcall vs cdecl 或反之亦然)。混合 Debug Release 也可能会带来问题。