2

我有错误处理代码,旨在捕获未处理的异常,然后创建转储。

现在,我遇到了一些在本机代码和托管代码之间转换时效果不佳的情况。

例如,如果在一个Paint()事件中我调用了一些本机代码,并且该本机代码引发了异常。
消息循环调度程序将捕获本机异常,然后重新抛出 .NET SEHException
托管 COM 对象的 DLLS 有时也会发生同样的情况。

这样做的问题是,由于堆栈回滚以及它捕获并SEHException从本机异常创建的方式,实际的本机调用堆栈被破坏了。

我可以使用 以某种方式获得本机调用堆栈SEHException吗?(请注意,SEHException 中的调用堆栈是 CLR 调用堆栈)。

或者我可以设置应用程序以便它以某种方式保存调用堆栈?

4

2 回答 2

1

试试 !dumpheap -type SEHException 。使用 SEHException 的地址打印 !pe异常地址。您将获得调用堆栈

于 2012-05-02T21:19:30.647 回答
1

发生的情况是.NetPaint()在需要绘制窗口时调用。
显然.Net使这非常安全,并增加了额外的预防措施和错误处理。

现在我的Paint()事件称为C++/CLI包装器 dll,它称为本机C++ dll。本机C++异常引发了访问冲突异常。

现在.Net捕获了该异常,并将其包装为托管SEHException对象,并且我已经丢失了实际错误点的所有调用堆栈。

解决方案:

我们需要在.Net异常处理之前捕获异常。
通常的异常处理流程可以在网上找到,但是这个站点给出了实际流程的一个很好的例子:异常处理程序

.Net 似乎在调用SetUnhandledExceptionFilter处理程序之前捕获了异常并将它们包装起来。

因此,我添加了第一次机会异常处理程序,AddVectoredExceptionHandler并通过检查错误代码来检查致命异常。

//SEH exceptions have code 0xC0000xxxx
#define SEH_TYPE (DWORD)0xC0000000L 
//mask the last byte
#define SEH_MASK (DWORD)0xFF000000L 
    LONG WINAPI CheckForSEHException( struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
    {   
        if ((lpTopLevelExceptionFilter->ExceptionRecord->ExceptionCode & SEH_MASK) == SEH_TYPE) //mask and check the last bits if it's an SEH exception
        {
            //handle exception here (create a dump or something)
            return EXCEPTION_EXECUTE_HANDLER;
        }
        return EXCEPTION_CONTINUE_SEARCH;
    }

异常代码可以在WinBase.h中找到,您可以按照实际错误代码的定义进行操作。(即寻找EXCEPTION_ACCESS_VIOLATION

于 2012-05-23T11:40:54.363 回答