是否有可能在.NET中捕获访问冲突异常?

时间:2010-07-22 18:18:29

标签: .net exception-handling unmanaged

我能做些什么来抓住AccessViolationException吗?它是由我无法控制的非托管DLL引发的。

5 个答案:

答案 0 :(得分:29)

你不应该。访问冲突是一个严重的问题:它是一种意外尝试写入(或读取)无效的内存地址。正如John已经阐明的那样,在提出访问冲突之前,非托管DLL可能已经损坏了进程内存。这可能会对当前流程的任何部分产生不可预测的影响。

最安全的做法是通知用户,然后立即退出。

更多详细信息:访问冲突是操作系统异常(所谓的SEH或结构化异常处理异常)。这是一种与System.Exception的托管CLR异常不同的异常。您很少会在纯托管代码中看到SEH异常,但如果出现这种情况,例如在非托管代码中,CLR会将其提供给托管代码,您也可以将其捕获到 1

但是,捕获SEH例外通常不是一个好主意。有关详细信息,请参阅MSDN杂志中的Handling Corrupted State Exceptions一文,其中包含以下文字:

  

CLR始终使用与程序本身引发的异常相同的机制向托管代码提供SEH异常。只要代码不尝试处理无法合理处理的异常条件,这就不是问题。在访问冲突后,大多数程序无法安全地继续执行。不幸的是,CLR的异常处理模型总是鼓励用户通过允许程序捕获System.Exception层次结构顶部的任何异常来捕获这些严重错误。但这很难做到。

1 直到.NET 3.5才这样。在.NET 4中,行为已被更改。如果您仍希望能够捕获此类异常,则必须将legacyCorruptedState­­ExceptionsPolicy=true添加到a​​pp.config。以上链接的更多细节。

答案 1 :(得分:8)

  

是。

在App.confg中,在<configuration>标记中输入以下代码:

<runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true"/>
</runtime>

现在你应该能够像其他任何一样捕获损坏的状态异常(CSE)。

注意:如果您已有运行时标记,则只需向其添加<legacyCorruptedStateExceptionsPolicy enabled="true"/>

即可

以上适用于.Net 4.5

答案 2 :(得分:6)

正如其他人指出的那样,你不应该“处理”这种情况,但在开发过程中,为了排除故障,抓住它是很方便的。

您可以使用System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions属性标记您的托管方法:

[HandleProcessCorruptedStateExceptions]
public void MyMethod()
{
    try
    {
        NaughtyCall();
    }
    catch (AccessViolationException e)
    {
        // You should really terminate your application here
    }
}

答案 3 :(得分:1)

首先,我完全熟悉0xA3。但是如果没有出路,你可以将脏的非托管dll包装在自己的进程中并通过IPC(TCP / IP,namedpipes等)传输数据。捕获所有异常并通知主机进程。因此,您的主机进程主要是通过内存损坏来节省的。

答案 4 :(得分:0)

您可以使用try-catch块将调用包装到非托管DLL。 AccessViolationExceptions可以正常捕获。执行以下代码会显示两条消息:

try
{
    throw new AccessViolationException();
}
catch (Exception e)
{
    MessageBox.Show(e.Message + e.StackTrace, e.Message, MessageBoxButtons.OK, MessageBoxIcons.Error);
}
MessageBox.Show("Still running..");

编辑: .NET 4引入了change in behavior,除非您专门"ask"运行时才能捕获已损坏的状态异常。