程序崩溃并出现 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 时应用程序崩溃并出现异常

使用sf :: Text数组时发生崩溃

catch(...) 没有捕获异常,我的程序仍然崩溃

ntdll 0XC0000005 Windbg 中的第一次机会异常

PostgreSql 因错误而崩溃:“服务器进程(PID XXXX)被异常 0xC0000142 终止”