2010-07-22 57 views

回答

26

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

最安全的事情是可能通知用户,然后立即退出。

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

然而,捕SEH异常大多不是一个好主意。进一步的细节在MSDN杂志文章Handling Corrupted State Exceptions在下面的文本从采取的解释:使用相同的机制,通过程序本身引起的异常

的CLR一贯提供的SEH例外托管代码。只要代码不尝试处理无法合理处理的异常情况,这就不成问题。访问冲突后,大多数程序无法安全地继续执行。不幸的是,CLR的异常处理模型一直鼓励用户通过允许程序捕获System.Exception层次结构顶部的任何异常来捕获这些严重错误。但这很少是正确的。

这是真的,直到.NET 3.5。在.NET 4中,行为已经改变。如果您仍然希望能够捕捉到这种异常情况,则必须将legacyCorruptedState­­ExceptionsPolicy=true添加到app.config。上面链接的进一步细节。

+4

澄清:您希望退出ASAP的原因是,您不知道非托管DLL在达到访问冲突之前被覆盖的内容。它可能在足够的地方编写垃圾,导致程序无法安全地继续。 – 2010-07-22 18:38:55

+0

@John Saunders:谢谢你的澄清。我更新了我的答案。 – 2010-07-22 18:47:31

+4

我可以想到一个非常好的理由来解决这个问题:如果你有一个无人管理的进程,而你没有这个进程,而不是退出,那么这个进程将会挂起,访问冲突对话框会显示没有人。捕捉它可让您在没有弹出对话框的情况下退出。 – jpwkeeper 2013-05-16 14:09:48

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"运行时这样做。

+0

的问题是,它是一个好主意,这样做?向用户显示一个友好的好消息并写入日志可能是明智的。但进一步工作不是一个好主意...... – rioki 2010-07-22 18:48:42

+0

可能不是,如果你不是绝对肯定的,至少不会发生什么不好的事情。 – andyp 2010-07-22 18:56:17

+2

这不起作用。我试过捕获异常和AccessViolationException,但它忽略了我的catch块。我假设有一些我需要的app.config标志。 – 2010-07-22 19:10:20

1

首先我用0xA3执行完全ACK。但是,如果没有出路,你可以将脏的非托管DLL包装在自己的进程中,并通过IPC(TCP/IP,namedpipes等)传输数据。捕获所有异常并通知主机进程。所以你的主机进程主要是从内存损坏中保存。

6

是。

在你的应用程序。CONFG,扑通的<configuration>标记中下面的代码:

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

现在,你应该能够赶上损坏的状态异常(CSE)像任何其他。

注意:如果你已经有一个运行时的标签,然后简单地添加<legacyCorruptedStateExceptionsPolicy enabled="true"/>

上述作品.NET 4.5

+1

为此。我读了几个关于这个问题的答案。所有人都说“将'legacyCorruptedStateExceptionsPolicy enabled =”true“/>'添加到'app.config'”,但没有人说这不应该在默认的“”部分。感谢提供''部分的提示 – user1234 2017-06-26 19:34:46

2

正如其他人指出的那样,你不应该“处理”这一条件,但在开发过程中,为了排除故障,很方便。

您可以标记与System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions属性的管理方法:

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