在 Win 10 中调试卸载 DLL 时发生崩溃,但在 Win 7 中则不然

2024-04-23

不完全确定我已经解决了这个问题,但这就是我所看到的和我所看到的think正在进行。

我有一个主要用 C 编写的 Win32 程序,用于加载 C++ DLL。该 DLL 通过 COM 对象(可能由 DLL 本身实例化的对象)将数据从 C 程序传递到另一个应用程序。所有这一切显然至少在 Windows XP 和 Windows 7 上运行良好(可能是 Win95 和 Win98,我需要更深入地回顾代码历史来找出这个接口是什么时候引入的),但在 Windows 10 中程序崩溃了在对该 DLL 的 FreeLibrary() 调用期间。

在调试器中检查这一点时,DLL_DETACH_PROCESS 似乎已成功处理(处理该消息时没有执行任何代码)。崩溃发生在代码离开入口点之后(或同时)。

如果继续单步执行,我最终会看到一个名为 utilcls.h 的头文件,它似乎是 Borland C Builder 6 头文件之一。我相信其中的模板代码与被拆除的COM对象有关。 Unbind() 调用通过,这是崩溃之前我可以执行的最后一行代码。

如果我使用调试器的 CPU 窗口并继续单步执行,则剩下的所有内容似乎都与崩溃发生之前释放内存有关,但要到达那里需要进行大量的 CPU 单步执行。

崩溃引发 APPCRASH 异常 0xc0000602,引用 Combase.dll。

只需不调用该 DLL 的 FreeLibrary 即可使应用程序成功关闭,但我的假设是 FreeLibrary 调用很重要。

COM 对象由数据共享应用程序在 FreeLibrary() 调用之前释放,从而允许该应用程序关闭。我目前的假设是,在较新的操作系统中,某些取消链接的情况有所不同,这导致了崩溃,但我不知道如何确定。

我的问题:

  • 如果对于其他更了解自己在做什么的人来说这是显而易见的,那么是什么导致了这次崩溃?

  • 尝试调试此问题的下一步是什么?我已经用尽了我所使用的调试环境的知识,但对 COM 或 DLL 的了解还不足以知道下一个要问的问题是什么。


RbMm 请求的一些调试器输出:

0:000:x86> t
ntdll_77b40000!RtlIsCriticalSectionLockedByThread+0x1b:
77b7256b c20400          ret     4
0:000:x86> t
combase!DecrementMTAUsageHelper+0x5b:
7527a2d6 85c0            test    eax,eax
0:000:x86> r eax
eax=00000001
0:000:x86> t
combase!DecrementMTAUsageHelper+0x5d:
7527a2d8 0f859a000000    jne     combase!DecrementMTAUsageHelper+0xfd (7527a378) [br=1]
0:000:x86> t
combase!DecrementMTAUsageHelper+0xfd:
7527a378 e89e9e0f00      call    combase!CrashProcessWithWERReport (7537421b)

此时,堆栈大致如下所示:

ChildEBP RetAddr  Args to Child              
0019f9b8 7527a37c 063f4248 753d8448 00000000 combase!CrashProcessWithWERReport+0x35
0019f9e8 75292bfc 753d8448 7529257e 00000000 combase!DecrementMTAUsageHelper+0x101
(Inline) -------- -------- -------- -------- combase!DecrementMTAUsage+0x9
0019f9f0 7529257e 00000000 00000000 00000000 combase!CDllHost::MTAUninitializeApartmentOnly+0xe
0019fa08 7527543a 00000000 063f4248 00712410 combase!CDllHost::ClientCleanupFinish+0x4d
0019fa30 75276361 00000000 0019fa8c 00000000 combase!DllHostProcessUninitialize+0xa0
0019fa58 7527a452 000d06f6 00712410 00000000 combase!ApartmentUninitialize+0xe4
0019fa70 752c2a1e 000d06f6 00712e18 00712e80 combase!wCoUninitialize+0xd0
0019fa94 74ed3e58 00000003 74c17ff1 a6d0e607 combase!CoUninitialize+0x7e
0019fa9c 74c17ff1 a6d0e607 000b0792 74ed48f0 imm32!CtfImmCoUninitialize+0x48
0019fb7c 74809ea6 00050004 000d06f6 00000000 msctf!TF_Notify+0x581
0019fb98 748080dc 00050004 000d06f6 00000000 user32!CtfHookProcWorker+0x36
0019fbe0 74807fa6 0019fc34 0019fc24 00000000 user32!CallHookWithSEH+0x5c
0019fc08 77bb0006 0019fc24 00000018 0019fc80 user32!__fnHkINDWORD+0x26
0019fc38 710623fb 000b0792 04ff11aa 05480e70 ntdll!KiUserCallbackDispatcher+0x36
0019fc50 050364e4 000b0792 050376d8 05480e70 apphelp!DWM8AND16BitHook_DestroyWindow+0x2b
0019fc8c 05051007 00000000 05055034 00000001 myDLL!myCOMObject_tlbFinalize+0x408a4
0019fcb4 050511c6 0019fcd0 00000001 04ff1318 myDLL!myCOMObject_tlbFinalize+0x5b3c7
0019fcd8 04ff13d3 05055034 77badcce 04ff0000 myDLL!myCOMObject_tlbFinalize+0x5b586
0019fd00 77b807c6 04ff1318 04ff0000 00000000 myDLL+0x13d3
0019fd50 77b6aa5e 00000000 00000000 259704e5 ntdll!LdrpCallInitRoutine+0x43
0019fdb8 77b6e6c8 00000000 0071dd60 00000000 ntdll!LdrpProcessDetachNode+0xbb
0019fdd8 77b6e5af 25970745 0071e560 c000022d ntdll!LdrpUnloadNode+0x100
0019fe18 77b6e4f6 004afcc4 004ae3a4 04ff0000 ntdll!LdrpDecrementModuleLoadCountEx+0xa7
0019fe38 746e9d56 04ff0000 006e33c5 00000000 ntdll!LdrUnloadDll+0x86
0019fe4c 0049261c 04ff0000 00000000 00493034 KERNELBASE!FreeLibrary+0x16
0019fe64 00441895 004afc98 fffffffe 0019fee8 rpopdbg!_GetExceptDLLinfo+0x914bf

现在正在处理剩下的事情,但我猜我需要弄清楚如何正确地对 COM 对象进行清理?也许是为了响应 DLL_DETACH_PROCESS?


崩溃引发 APPCRASH 异常 0xc0000602,参考回 combase.dll

combase.dll used 0xc0000602 (STATUS_FAIL_FAST_EXCEPTION) 代码仅来自

void CrashProcessWithWERReport();

(这称为RaiseFailFastException https://msdn.microsoft.com/en-us/library/windows/desktop/dd941688(v=vs.85).aspx用这个代码)

CrashProcessWithWERReport仅从以下位置调用DecrementMTAUsageHelper满足 2 个条件 -CoDecrementMTAUsage https://msdn.microsoft.com/en-us/library/windows/desktop/jj151606(v=vs.85).aspx呼叫次数多于CoIncrementMTAUsage https://msdn.microsoft.com/en-us/library/windows/desktop/jj151607(v=vs.85).aspx or (我几乎可以肯定,因为这个原因) DecrementMTAUsageHelper当调用线程持有Loader临界区时调用——因此在DLL加载或卸载过程中。来自 MSDN

进程关闭期间不要调用 CoDecrementMTAUsage或里面 DLL主程序。您可以在调用开始之前调用 CoDecrementMTAUsage 关机过程。

所以我的猜测 - 一些代码调用CoDecrementMTAUsage https://msdn.microsoft.com/en-us/library/windows/desktop/jj151606(v=vs.85).aspx在你的DLL卸载过程中(当你调用FreeLibrary)

你的DLL不能直接调用CoIncrementMTAUsage https://msdn.microsoft.com/en-us/library/windows/desktop/jj151607(v=vs.85).aspx / CoDecrementMTAUsage https://msdn.microsoft.com/en-us/library/windows/desktop/jj151606(v=vs.85).aspx因为这个新的 API 是从 win 8 开始存在的(还要检查你在 win 8.1 上的代码 - 我认为也会崩溃),但是这个 api 可以从其他系统组件间接调用。

我可以假设你的DLL没有直接释放一些使用过的资源或者你调用FreeLibrary当 DLL 仍然持有一些资源时(所以你调用FreeLibrary没有从 DLL 进行适当的清理调用),因此该资源开始释放(CoDecrementMTAUsage) 卸载过程中

尝试调试此问题的下一步是什么?

您需要使用符号文件进行调试(例如使用 winDbg)。设置断点于DecrementMTAUsageHelper, CoDecrementMTAUsage有可能CoIncrementMTAUsage- 我打的电话对吗RtlIsCriticalSectionLockedByThread return TRUE(这个API从开始调用DecrementMTAUsageHelper).

无论如何,将线程调用堆栈发布在DecrementMTAUsageHelper呼叫点(就在崩溃之前)并且可能在CoIncrementMTAUsage too

- - - - - - - - - - - 编辑 - - - - - - - - - - - - -

通过查看 DLL 调用可见的堆栈跟踪DestroyWindow来自 DllMain。

apphelp!DWM8AND16BitHook_DestroyWindow

这是错误,只有两个原因 - 首先 - 阅读本文 https://blogs.msdn.microsoft.com/oldnewthing/20090626-00/?p=17733 -

获取DLL_PROCESS_DETACH通知的线程不是 必然是获得 DLL_PROCESS_ATTACH 通知的那个。你 无法在 DLL_PROCESS_ATTACH 中对线程关联执行任何操作,或者 DLL_PROCESS_DETACH 处理程序,因为您无法保证哪个 将调用线程来处理这些进程通知。这 这是一个典型的例子,我被告知开发者支持团队正在运行这个例子 以惊人的频率进入,是一个DLL,它在其内部创建一个窗口 DLL_PROCESS_ATTACH 处理程序并在其 DLL_PROCESS_DETACH 中销毁它 处理程序。

但是你的崩溃是由于另一个原因,没有在文章中列出 - DllMain 有很多限制 https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx#general_best_practices,里面有什么不能叫的。尽管DestroyWindow此处未直接列出,但如您的情况所示 - 这是非法调用(即使我们在创建此窗口的同一个线程上调用) - 当您的窗口被销毁时imm32.CtfImmNotify(msctf!TF_Notify)叫做

0019fa9c 74c17ff1 a6d0e607 000b0792 74ed48f0 imm32!CtfImmCoUninitialize+0x48
0019fb7c 74809ea6 00050004 000d06f6 00000000 msctf!TF_Notify+0x581
0019fb98 748080dc 00050004 000d06f6 00000000 user32!CtfHookProcWorker+0x36
0019fbe0 74807fa6 0019fc34 0019fc24 00000000 user32!CallHookWithSEH+0x5c

结果取消初始化 https://msdn.microsoft.com/en-us/library/windows/desktop/ms688715(v=vs.85).aspx is 从 DllMain 调用 !

来自 MSDN

不要从 DllMain函数。

这里里面FINAL 取消初始化 https://msdn.microsoft.com/en-us/library/windows/desktop/ms688715(v=vs.85).aspx called DecrementMTAUsage这决定了我们通过调用来锁定加载器内部RtlIsCriticalSectionLockedByThread and CrashProcessWithWERReport called.

解决方案 ?

当然最好是修复 DLL,但如果这是不可能的 - 认为下一个“黑客”将会起作用

HRESULT hr = CoInitialize(0); // asume that we in STA
FreeLibrary(hDLL); 
if (0 <= hr) CoUninitialize();

有了这个取消初始化 https://msdn.microsoft.com/en-us/library/windows/desktop/ms688715(v=vs.85).aspx当然无论如何都会被调用imm32!CtfImmCoUninitialize但这将是不是最终版本取消初始化并作为结果DecrementMTAUsage不会被调用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Win 10 中调试卸载 DLL 时发生崩溃,但在 Win 7 中则不然 的相关文章

  • Active Directory:获取用户所属的组

    我想找到用户所属的组列表 我尝试了几种解决方案http www codeproject com KB system everythingInAD aspx http www codeproject com KB system everyth
  • C++11 类型推导与 const char *

    In GotW 94 http herbsutter com 2013 08 12 gotw 94 solution aaa style almost always auto Herb Sutter 对 经典 C 声明进行了区分 const
  • 如何通过 C# 检测字符串中的阿拉伯语或波斯语字符?

    我想检测Arabic or Persian字符串中的字符 例如 在字符串中搜索 15 Aspire ES1 533 C4UH 并返回true 并在字符串中搜索 Aspire ES1 533 C4UH 并返回false string patt
  • Task.Delay 是否真的像 I/O 操作一样异步,即它依赖于硬件和中断而不是线程?

    我发现了大量相关内容 但这些内容都是拐弯抹角的 但我始终无法找到答案 我几乎 100 确定Task Delay int 不使用线程 因为我可以在只有 16 个逻辑处理器的机器上运行此代码 var tasks new List
  • 欢迎消息在网络聊天中不可见,但可以在模拟器中使用

    IConversationUpdateActivity update message using var scope Microsoft Bot Builder Dialogs Internals DialogModule BeginLif
  • 创建新视图时如何初始化视图模型中的属性?

    我有一个应用程序 可以打开一个视图 允许您搜索数据 然而 为了进行搜索 用户必须选择他想要在什么类别下进行搜索 目前 我正在尝试弄清楚如何将所选类别从主视图模型 作为 int 传递到新搜索视图的视图模型 目前我正在尝试在主视图中使用类似的东
  • 如何保存具有多个缩进设置的XmlDocument?

    我需要保存一个XmlDocument以适当的缩进归档 Formatting Indented 但有些节点及其子节点必须排在一行 Formatting None 从那时起如何实现这一目标XmlTextWriter接受整个文档的设置 在 Ahm
  • 编译使用Basler相机的程序

    我正在尝试使用 Basler 相机捕获图像的 C 程序来工作 我拿到 来自制造商的代码 它应该 非常容易使用 但是 链接它有 成为一场噩梦 我的 C 时代已经过去了 最近只使用 Matlab 所以我可能会犯一些愚蠢的错误 但请赐教 代码如下
  • 为什么不能使用 C# 对象初始值设定项语法调用方法? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 消息在事务处理时未到达 MSMQ

    我在本地计算机中创建了一个私有 MSMQ 我使用以下 C 代码将消息发送到队列 当我将队列更改为事务性队列时 消息未到达 MSMQ 但是 Send 方法中没有抛出异常 我需要做出什么改变才能使其发挥作用 using System using
  • Compact Framework 3.5 上的 System.Data.SQLite 问题

    我在我的紧凑框架应用程序中使用 sqlite 来记录系统中的事件 我也在使用系统 数据 SQLite http sqlite phxsoftware com 该事件具有描述其发生时间的时间戳 我将此时间戳记作为刻度存储在我的表中 除此列外
  • 仅使用 url 嵌入视频

    给定一个 youtube url 我如何使用 net c 将视频嵌入到页面中 只需添加如下一行 将 autoplay 设置为 0 或 1 取决于您是否希望人们真正留在您的页面上
  • GoogleTest:如何跳过测试?

    使用 Google Test 1 6 Windows 7 Visual Studio C 如何关闭给定的测试 又名如何阻止测试运行 除了注释掉整个测试之外 我还能做些什么吗 The docs https github com google
  • 企业库 CacheFactory.GetCacheManager 抛出空引用

    我正在尝试将使用 1 1 版本的企业库缓存块的应用程序转换为 2 0 版本 我认为我真正遇到的问题是不同 EntLib 部分的配置被分成几个文件 显然 这曾经是由ConfigurationManager 部分处理程序 但现在已经过时 取而代
  • 以编程方式将 Word 文件另存为图片

    我想将Word文档的第一页另存为图片 使用 C 有什么方法可以做到这一点 您可以将 Word 文档打印到 XPS 文档 在 WPF Net 3 5 应用程序中打开它 并使用 WPF 框架的文档和图像功能将第一个内部固定页面对象转换为位图 如
  • AZURE:workerrole 中的异步 Run()

    我有一个异步任务 async Task UploadFiles 我想在 azure 工作者角色的 Run 方法中调用 UploadFiles 上的 等待 但 await 仅适用于声明为异步的方法 那么我可以使 Run 方法异步 如下所示 p
  • 使用 MVVM 绑定 Xamarin.Forms 中的属性

    我在使用 Xamarin Forms 和 MVVM 制作游戏时遇到问题 游戏中有一艘由用户控制的潜艇 并且有水雷掉落 因此用户必须避开这些水雷 这些地雷是在运行时使用 2 个计时器生成的 因此我用 XAML 中的 CollectionVie
  • C# StreamReader 使用分隔符保存到数组

    我有一个文本文件 其中包含制表符分隔的数据 我在 C 应用程序中需要的是从文本文件中读取一行并将它们保存到一个数组中 在每个位置将它们分开 t 然后我对下一行做同样的事情 My code StreamReader sr new Stream
  • 在 C 中打印字符串的所有排列

    我正在学习回溯和递归 并且我陷入了打印字符串所有排列的算法 我用以下方法解决了它贝尔算法 http programminggeeks com bell algorithm for permutation 用于排列 但我无法理解递归方法 我在
  • SQL 注入在 winform 中有效吗?

    我正在用 C 制作一个 Windows 软件 我读过关于sql injection但我没有发现它适用于我的应用程序 SQL 注入在 winform 中有效吗 如果是的话如何预防 EDIT 我正在使用文本框来读取用户名和密码 通过使用 tex

随机推荐

  • 通过css替换图片

    我正在 Stylish 一个 Firefox 插件 中编写代码来更改显示的图像 image 属性没有 div 标签 所以我必须使用它 img src s dschjungelplanet 因此 这将替换页面中任何位置的 img src 中的
  • 使用多个提供程序的客户端应用程序应使用什么设计/模式?

    这是一个与设计相关的问题 假设我们有一个名为 ClientAPI 的公共 API 其中包含一些 Web 方法 例如 CreateAccount GetAccount 根据客户的不同 我们使用许多不同的提供商来满足这些请求 假设我们有 Pro
  • 如何在Python中在后台运行长时间运行的作业

    我有一个运行长时间运行的作业 大约几个小时 的网络服务 我正在使用 Flask Gunicorn 和 nginx 来开发它 我想做的是让需要很长时间才能完成的路线 调用创建线程的函数 然后 该函数将向路由返回一个 guid 并且路由将返回一
  • C# FileSystemWatcher 和 FTP

    我通过文件系统观察器监视在 ftp 上删除的文件 然后移动到另一个目录 现在我触发文件系统观察程序的创建事件的复制 但显然在 ftp 的情况下 创建只是一个存根文件 数据会进入并在上传时填充文件直至完成 任何人对此都有一个优雅的解决方案 或
  • Python Mogo ImportError:无法导入名称连接

    不明白为什么这不起作用 mogo 0 2 4 File Users Sam Envs AdiosScraper lib python2 7 site packages mogo connection py line 3 in
  • 将单词的第一个字母大写,同时删除空格(Haskell)

    我刚刚开始使用 Haskell 这就像我正在写的第三件事 所以 自然地 我发现自己有点困惑 我正在尝试编写一些代码 该代码将获取一个字符串 删除空格 并将该字符串的每个字母大写 例如 如果我输入 这是一个测试 我想返回类似 thisIsAT
  • HierarchyID 如何从子级获取所有父级

    我对菜单的层次结构 ID 和用户权限有疑问 例如 我只想为用户提供 4 级的权限 并且我的查询应自动从 4 级子级中选择所有父级 这个怎么做 你明白我的问题吗 我只想要孩子的所有父母 祖先 问候曼努埃尔 我最近一直在使用 Hierarchy
  • 如何在 WPF 中折叠星形大小的网格列?

    通过设置使三列具有相同的宽度Width to Auto
  • 如何防止键盘隐藏我的EditText?

    我在顶部有一个relativeLayout 然后在下面的中心有一个ListView 最后在底部我有另一个relativeLayout 里面有一个EditText和一个Button 我希望当我单击 EditText 并出现 IME 虚拟键盘
  • 连接到 ACCESS 2007 (ODBC) 时如何在 PHP 上设置 UTF8

    我在 Access 文件中有泰文 日文 韩文字符 3 个字段 我在 PHP 中创建了一个脚本来连接到该文件 但显示的字符显示 和 设置什么才能显示正常字符 这是我的脚本
  • 使用 Unicode 字符打印 Pandas 列

    我有一个 pandas 数据框 其中有一列包含 unicode 编码名称 import pandas as pd no unicode pd Series Steve Jason Jake yes unicode pd Series tea
  • 在 Python 中将视频源从 Javascript 传递到 OpenCV

    我正在尝试创建一个网络应用程序来检测实时视频源中的面孔 我已经用 Javascript 编写了网络摄像头源代码 因为我想稍后托管该应用程序 使用 Javascript 获取 feed 的代码 var video document query
  • 选择公平的团队——并用数学来证明这一点

    应用 类似于选择操场团队 我必须将 n 个按顺序排列的元素的集合分成 n 2 的两队 团队必须尽可能 均匀 如上所述 从游乐场团队的角度考虑 偶数 排名表明相对 技能 或价值水平 元素 1 值 1 个 点 元素 2 值 2 个 点 等等 没
  • 模块元数据版本不匹配错误

    我在尝试构建我的角度项目时遇到此错误 模块元数据版本不匹配错误 C Users Admin ifish web node modules angular2 cool storage index d ts 找到版本 4 预期版本 3 解析符号
  • 从 WebView 从我自己的网页获取 html 元素?

    我有一个网络视图 显示来自我自己的服务器的页面 是否可以添加一个 javascript 方法 允许我的 Android 应用程序从 web 视图中读出页面元素 就像是 mypage html p some data p my android
  • Windows 上的 Jenkins 与 Docker - 无法运行程序“nohup”

    我正在使用Jenkins Azure VM 代理插件 https plugins jenkins io azure vm agents与 Linux Master 一起在 Windows 代理上启动作业 我已经完成了所有配置步骤 一切正常
  • java.lang.IllegalArgumentException:由于密钥无效而无法初始化

    我遇到加密异常 我在跑 操作系统 X 10 11 爪哇1 8 Groovy 版本 2 4 4 摇篮2 3 20141027185330 0000 JAVA HOME Library Java JavaVirtualMachines jdk1
  • 无法在 debian 上安装 node-libcurl

    请告诉我为什么我无法安装 node libcurl 以下是安装 npm install node libcurl 时显示的错误 gt email protected cdn cgi l email protection install va
  • Django-filter 1.1.0 中的多个模型

    我想为网站的最终用户实现一个过滤器 以便他们可以按价格 评级 性别和位置进行过滤 这里的问题是价格和评级存储在模型类 评论 中 位置和性别存储在模型类 冒险 中 在 comment 类中 adventure 由外键引用 如何在filters
  • 在 Win 10 中调试卸载 DLL 时发生崩溃,但在 Win 7 中则不然

    不完全确定我已经解决了这个问题 但这就是我所看到的和我所看到的think正在进行 我有一个主要用 C 编写的 Win32 程序 用于加载 C DLL 该 DLL 通过 COM 对象 可能由 DLL 本身实例化的对象 将数据从 C 程序传递到