2011-04-08 39 views
1

我们有一个调用非托管C++主要功能的.NET程序。我在.NET一侧有一个全局的异常捕获器来捕获任何未处理的错误,但是如非托管C++ DLL中的访问冲突等错误会导致程序无法记录。在DLL中添加“全局”异常捕获器的最佳方法是什么?我可以在DllMain中做这个吗?如何捕获DLL中的错误

回答

1

您可以使用/EHa异常处理标志,这将导致您的C++ catch (...)还捕获结构化的异常,即访问冲突。这个缺点是你看不到什么是异常。

或者,您可以使用构造的异常处理程序__try { } __except(FILTER) { }来处理结构化异常。这允许你输出被捕获的异常类型。但是,对于可以在具有__try的函数中执行的操作(如没有C++异常处理或具有析构函数的对象)有限制。

但是,您可以通过调用包含C++异常处理和原始代码的函数来解决__try的限制。

void main() { 
    __try { 
    Foo(); 
    } 
    __except(EXCEPTION_EXECUTE_HANDLER) { 
    // Log some error regarding the structured exception 
    } 
    return 0; 
} 

void Foo() { 
    try { 
    SomeCPPObject bar(1,2); 
    DoSomeStuff(); 
    } 
    catch (const std::exception&) { 
    // Log the C++ exception 
    } 
} 

要小心,但是,因为通常一个结构化的异常上升后,不应该继续执行,因为你的程序的状态可能被彻底摧毁。最好只在退出之前使用这种类型的异常处理来记录错误。

+0

小心!不允许在应用程序中混合使用SEH和C++异常。我很难找到详细说明这一点的MSDN页面,但同时这里是一个链接:(http://msdn.microsoft.com/en-us/library/x057540h.aspx)。请参阅“另请参阅”一行,其中指出:“不要混合错误处理机制[...]” – RobH 2011-04-08 15:38:44

+0

这里有更多信息:(http://msdn.microsoft.com/en-us/ library/7w0chfbk.aspx) – RobH 2011-04-08 15:41:45

+0

您的示例显示了主例程,但主要部分是托管的。我通过P/Invoke调用非托管DLL,它们是导致错误的那些DLL。 – erict 2011-04-10 17:25:46

1

CLR无法捕获由本机代码启动的线程中引发的任何硬件异常。这样做的唯一方法是使用SetUnhandledExceptionFilter(),注册的回调在Windows将要拆除进程之前由Windows调用。

在一个也包含托管代码的程序中使用它会充满陷阱和陷阱。 CLR也使用它,它必须为了生成NullReferenceException和DivideByZeroException之类的异常。你必须非常小心,不要打破这一点。做一些像调用GetThreadId()一样的东西,并且只过滤你知道的原生线程的异常是很重要的。接下来你要做的就是使用MiniDumpWriteDump()来生成一个小型转储,以便调试崩溃。