【问题标题】:Win32 DLL importing issues (DllMain)Win32 DLL 导入问题 (DllMain)
【发布时间】:2010-05-27 23:26:50
【问题描述】:

我有一个本地 DLL,它是另一个应用程序的插件(我对它的控制基本上为零)。一切都很好,直到我链接了一个额外的 .lib 文件(将我的 DLL 链接到另一个名为 ABQSMABasCoreUtils.dll 的 DLL)。此文件包含我想使用的父应用程序的一些附加 API。我什至没有编写任何代码来使用任何导出的函数,但只是在这个新的 DLL 中链接会导致问题。具体来说,当我尝试运行程序时出现以下错误:

应用程序未能正确初始化 (0xc0000025)。单击确定以终止应用程序。

我相信我在某处读到这通常是由于 DllMain 函数返回 FALSE。此外,以下消息将写入标准输出:

错误:在组件初始化之前尝试分配内存

我几乎 100% 确定此错误消息来自应用程序,而不是某种类型的 Windows 错误。

进一步研究这个问题(也就是翻来覆去并翻转我所知道的每个开关)我打开 /MAP 链接并在生成的 .map 文件中找到了这个:

 0001:000af220       ??3@YAXPEAX@Z              00000001800b0220 f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
 0001:000af226       ??2@YAPEAX_K@Z             00000001800b0226 f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
 0001:000af22c       ??_U@YAPEAX_K@Z            00000001800b022c f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
 0001:000af232       ??_V@YAXPEAX@Z             00000001800b0232 f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll

如果我使用“undname”取消装饰这些名称,它们会给出以下内容(相同的顺序):

void __cdecl operator delete(void * __ptr64)
void * __ptr64 __cdecl operator new(unsigned __int64)
void * __ptr64 __cdecl operator new[](unsigned __int64)
void __cdecl operator delete[](void * __ptr64)

我不确定我是否理解 ABQSMABasCoreUtils.dll 中的任何内容如何存在于此 .map 文件中,或者如果我没有任何引用此 DLL 的代码,为什么我的 DLL 甚至试图加载 ABQSMABasCoreUtils.dll。谁能帮我把这些信息放在一起,找出为什么这不起作用?值得我通过“dumpbin”确认父应用程序导入ABQSMABasCoreUtils.dll,所以无论如何它都会被加载。我也尝试过延迟在我的 DLL 中加载这个 DLL,但这并没有改变结果。

编辑

我已经仔细检查过,所有涉及的文件都是 64 位的。

【问题讨论】:

  • 您是否尝试过使用LoadLibrary 而不是导入库的静态链接?如果你这样做,你的主应用程序已经初始化,你有一些优势。
  • 我想到了这一点,但我最终会使用这个库中的大量函数。我不必为每个人使用 GetProcAddress 吗?如果可能的话,我宁愿避免这种情况。
  • C0000025 = STATUS_NONCONTINUABLE_EXCEPTION。尝试在 windbg 中运行应用程序,看看它在哪里崩溃;也许这会给你一个提示。

标签: c++ winapi abaqus


【解决方案1】:

我刚刚遇到了同样的问题。这是 Abaqus API 的问题,而不是加载 DLLS 的问题。

我认为这是因为 Abaqus API 覆盖了 new 和 delete 函数(您似乎已经注意到了)。如果您在程序中调用 new 或 delete,在初始化 Abaqus API 之前,例如通过调用 odb_initializeAPI();,那么您将获得

错误:在组件初始化之前尝试分配内存

错误消息和程序崩溃。

在我的程序中,在第一个 new 之前调用 odb_initializeAPI(); 解决了问题。

【讨论】:

  • 修复这个问题已经有一段时间了,但我遇到了一些不同的问题。我实际上是在用户子例程中访问 ODB,所以我使用的是 getActiveOdb()。我收到此错误是因为我在编译时依赖于 msvcr90.dll,而 Abaqus 正在使用 msvcr80.dll。但我很高兴您发布了以上内容 - 很难在线找到 Abaqus 用户子例程和后处理器的快速帮助。
  • @brady 你是如何识别和修复依赖问题的?我相信msvcr100.dll 与我的程序中的msvcr80.dll 冲突。我非常感谢您对此的帮助。
  • 我不记得我是如何识别它的 - 我可能使用了“dumpbin /imports”实用程序并注意到了冗余的 C++ 运行时库。为了解决这个问题,我必须使用 Visual C++ 8.0 (Visual Studio 2005) 构建,它是该版本 Abaqus 支持的 C++ 编译器。您可以在此处查看支持的编译器:Abaqus System Requirements。选择适当的版本并单击系统要求,选择您的平台,然后查找 C++ 编译器要求。
  • @brady 我正在使用 Visual Studio 2010。我安装了一个名为 Daffodil 的小实用程序,它使您能够链接到旧版本的 CRT 库(VS 2010 支持本机多目标)。我运行了 Dependency Walker,包含的唯一 CRT 库是 v80 (msvcr80.dll)。我认为这会解决我的问题,但我仍然无法让程序运行。调试器的堆栈跟踪显示程序在 Abaqus DLL 内崩溃。
  • @Derek 可能由于其他原因而崩溃。它崩溃的功能是否提供任何提示?您是从用户子例程访问 ODB 还是创建自己的后处理可执行文件?如果是后者,我建议您使用abaqus make 实用程序。此外,对于在 Windows 和 Linux 上与 Abaqus(用户 subs、exes、Python 等)进行大量交互的人来说,尽可能使用支持的编译器是一个非常好的主意。尤其是当您的构建变得越来越复杂并依赖于更多库等时。
【解决方案2】:

好吧,您肯定会引用该库的导入。如果不使用 new 或 delete 运算符,很难编写 C++ 程序。处理认为需要覆盖这些运营商的 CRT 版本的 3rd 方软件已经够难的了,如果它不允许你调用它们,直到它认为时机成熟,它是不可能的。放弃所有希望或向供应商寻求帮助。

【讨论】:

  • 大型 C++ 程序是否经常覆盖这些常用运算符?这似乎很愚蠢。是否可以使用 /DEFAULTLIB 解决这个问题?
  • 它只在愚蠢的程序和基础样式类库中很常见,它们依赖于所有代码与它们链接。你无法绕过它。破解 .lib 只会在某些代码使用分配器而其他代码不使用时带来痛苦。那是自动内存泄漏或 AV。
【解决方案3】:

加载 ABQSMABasCoreUtils.dll 期间出错的可能原因之一是找不到某些依赖模块(包括延迟加载 DLL)。使用 Dependency Walker(参见 http://www.dependencywalker.com/)检查 ABQSMABasCoreUtils.dll 的所有依赖项。

我有两个建议:

  1. 验证您是否可以加载关于LoadLibrary 的 ABQSMABasCoreUtils.dll。您不需要从 ABQSMABasCoreUtils.dll 调用任何函数。 LoadLibrary 的使用我不认为是最终解决方案。这只是一个诊断测试。通过测试,您可以验证是否存在在程序中加载 ABQSMABasCoreUtils.dll 的一般问题,或者存在某种进程初始化问题。
  2. 如果加载关于LoadLibrary 的 ABQSMABasCoreUtils.dll 将失败,则使用 Dependency Walker 的分析功能对加载 ABQSMABasCoreUtils.dll 期间完成的所有调用进行协议。另一种方法是使用 Process Monitor(参见 http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx)来跟踪加载 ABQSMABasCoreUtils.dll 期间将执行哪些文件和注册表操作。

如果LoadLibrary 没有失败,那么你确实有DLL 的初始化问题。通常,如果 DllMain 中的 DLL 尝试使用另一个 DLL 中尚未初始化的函数(尚未从 DllMain 返回),则通常会出现问题。在开始诊断此问题之前,我们应该尝试排除LoadLibrary 的更简单问题。

【讨论】:

    【解决方案4】:

    ABQSMABasCoreUtils.dll 看起来像是在导入 64 位函数。你的dll也是64位的吗?如果不是,那就是问题所在 - 您不能在同一进程中混合为不同架构编译的 DLL。

    【讨论】:

    • 如果是这种情况,代码将无法编译——不会在运行时失败。
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 2011-04-02
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    相关资源
    最近更新 更多