程序崩溃并出现 0xC000000D 并且没有异常 - 我该如何调试它?
Posted
技术标签:
【中文标题】程序崩溃并出现 0xC000000D 并且没有异常 - 我该如何调试它?【英文标题】:Program crashes with 0xC000000D and no exceptions - how do I debug it? 【发布时间】:2010-11-22 07:16:20 【问题描述】:我有一个使用第三方库的 Visual C++ 9 Win32 应用程序。当使用一组特定参数调用该库中的函数时,程序会因“异常代码 0xC000000D”而崩溃。
我尝试附加 Visual Studio 调试器 - 没有抛出异常(C++ 也没有类似访问冲突的结构),也没有调用 terminate()
。程序仍然默默地结束。
程序只是异常结束但没有在调试器中停止是怎么发生的?如何定位问题?
【问题讨论】:
是多线程还是单线程? @Simone:一个工作线程,多个由 RPC 产生的服务线程。我们彻底测试了同步,多线程不太可能是问题。 您运行的是发布版还是调试版?我见过一些奇怪的发布版本没有在调试器中停止的情况。 @Ori Osherov:在这种情况下,两个版本的行为方式相同。 很多好的想法 - 所有这些都会被 WinDbg 捕捉到,你会确切地知道发生了什么。捕获所有这些错误的另一种方法是使用 AppVerifier - 无需为 BoundsChecker 付费。 【参考方案1】:那是 STATUS_INVALID_PARAMETER,使用 WinDbg 追踪是谁扔了它(即附加 WinDbg,sxe eh
然后g
。
【讨论】:
OP 已经说过“附加 VS 调试器 - 不抛出异常”...... WinDbg 将如何改变图片? 四处搜索似乎表明有些函数会抛出这个问题 - 但也有些函数使用 STATUS_INVALID_PARAMETER 作为返回值。所以也许毕竟什么都没有抛出...... @Martin VS 会隐藏某些它不知道如何处理的异常(很少)。使用 WinDbg 100% 排除任何类型的异常。 如果我们没有从图书馆供应商那里得到帮助,我会试试这个。我还发现了这篇关于如何在这种情况下使用 WinDbg 的有前途的知识库文章:support.microsoft.com/kb/313109/en-gb @AnaBetts 我不这么认为,你有声明的来源吗?【参考方案2】:该问题的其他答案和 cmets 帮助很大。这就是我所做的。
我注意到,如果我在 Visual Studio 调试器下运行程序,它只会静默结束,但如果我在没有调试器的情况下运行它,它会崩溃并出现一个消息框(通常的 Windows 消息框说我丢失了未保存的数据,每个人都非常抱歉)。
所以我在没有调试器的情况下启动了程序,让它崩溃,然后 - 当消息框仍然存在时 - 附加调试器并点击“Break”。这是调用堆栈:
ntdll.dll!_KiFastSystemCallRet@0()
ntdll.dll!_ZwWaitForMultipleObjects@20() + 0xc bytes
kernel32.dll!_WaitForMultipleObjectsEx@20() - 0x48 bytes
kernel32.dll!_WaitForMultipleObjects@16() + 0x18 bytes
faultrep.dll!StartDWException() + 0x5df bytes
faultrep.dll!ReportFault() + 0x533 bytes
kernel32.dll!_UnhandledExceptionFilter@4() + 0x55c bytes
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//OurCodeInvokingThirdPartyLibraryCode
很明显这是三方库内部的一些问题。根据 MSDN,UnhandledExceptionFilter()
在致命情况下被调用,显然调用是由于库代码中的一些问题而完成的。因此,我们将首先尝试与库供应商解决问题。
【讨论】:
【参考方案3】:如果您没有 3rd 方库的源代码和调试信息,您将无法使用调试器单步执行它。在我看来,您的选择是;
整理一个简单的测试用例来说明崩溃并将其发送给库开发人员 将该库函数包装在您自己的代码中,以检查非法参数并在您自己的应用程序传递这些参数时抛出异常/返回错误代码 重写库中不起作用的部分或使用替代方法很难修复仅作为对象提供的代码
编辑您还可以在主消息循环周围使用 __try __finally 更优雅地退出,例如
int CMyApp::Run()
__try
int i = CWinApp::Run();
m_Exitok = MAGIC_EXIT_NO;
return i;
__finally
if (m_Exitok != MAGIC_EXIT_NO)
FaultHandler();
【讨论】:
@Paul,当然,但仅限于没有 PDB 的汇编程序中。使用 PDB 但没有源代码,您可以使用源代码中的标签很好地注释汇编程序。 IMO,这些很少值得手动调试,因为必须在汇编程序中进行修复,这将非常耗时并导致未来的维护噩梦。 我不认为 OP 的问题在于进入代码,而是捕获异常,他说这不会发生。 但他不想手动调试程序集,他想要故障点的调用堆栈(甚至是错误的)。如果故障实际上是由操作系统引发的,他将有相应的符号以上是关于程序崩溃并出现 0xC000000D 并且没有异常 - 我该如何调试它?的主要内容,如果未能解决你的问题,请参考以下文章
重装系统黑屏提示winload.exe 0xc000000d错误无法完成安装?
使用 javax.microedition.media.Player 时应用程序崩溃并出现异常