如何处理AccessViolationException


183

我正在从.net应用程序中使用COM对象(MODI)。我正在调用的方法将引发System.AccessViolationException,它会被Visual Studio拦截。奇怪的是,我将调用包裹在一个try捕获中,该捕获具有用于AccessViolationException,COMException和其他所有内容的处理程序,但是当Visual Studio(2010)拦截AccessViolationException时,调试器会中断方法调用(doc.OCR),如果我单步执行,它将继续到下一行而不是进入catch块。此外,如果我在Visual Studio之外运行此程序,则应用程序将崩溃。如何处理在COM对象中引发的异常?

MODI.Document doc = new MODI.Document();
try
{
    doc.Create(sFileName);
    try
    {
        doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false);
        sText = doc.Images[0].Layout.Text;
    }
    catch (System.AccessViolationException ex)
    {
        //MODI seems to get access violations for some reason, but is still able to return the OCR text.
        sText = doc.Images[0].Layout.Text;
    }
    catch (System.Runtime.InteropServices.COMException ex)
    {
        //if no text exists, the engine throws an exception.
        sText = "";
    }
    catch
    {
        sText = "";
    }

    if (sText != null)
    {
        sText = sText.Trim();
    }
}
finally
{
    doc.Close(false);

    //Cleanup routine, this is how we are able to delete files used by MODI.
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
    doc = null;
    GC.WaitForPendingFinalizers();
    GC.Collect();
    GC.WaitForPendingFinalizers();

}

您是否尝试过将Exception处理程序放入(临时!)以捕获所有异常并查看异常实际是什么?
克里斯·

3
@ChrisF-是的,看到最后一个捕获处理程序了吗?那应该捕获所有东西,包括Exception和Exception的任何子类。同样,Visual Studio报告该异常是System.AccessViolationException
Jeremy 2010年

Answers:


299

在.NET 4.0中,运行时将作为Windows结构化错误处理(SEH)错误引发的某些异常作为损坏状态的指示符进行处理。这些受破坏状态异常(CSE)不允许被您的标准托管代码捕获。我不会在这里介绍原因或方式。阅读有关.NET 4.0框架中CSE的文章:

http://msdn.microsoft.com/zh-CN/magazine/dd419661.aspx#id0070035

但是有希望。有几种方法可以解决此问题:

  1. 重新编译为.NET 3.5程序集,然后在.NET 4.0中运行它。

  2. 在配置/运行时元素下,在应用程序的配置文件中添加一行: <legacyCorruptedStateExceptionsPolicy enabled="true|false"/>

  3. 使用HandleProcessCorruptedStateExceptions属性装饰要捕获这些异常的方法。有关详细信息,请参见http://msdn.microsoft.com/zh-cn/magazine/dd419661.aspx#id0070035


编辑

以前,我引用了一个论坛帖子以获取更多详细信息。但是,由于Microsoft Connect已淘汰,因此,如果您有兴趣,以下是其他详细信息:

来自Microsoft CLR团队的开发人员Gaurav Khanna

此行为是设计导致的,这归因于CLR 4.0的一项功能,称为“损坏的状态异常”。简而言之,托管代码不应尝试捕获表示损坏的进程状态的异常,而AV就是其中之一。

然后,他继续参考HandleProcessCorruptedStateExceptionsAttribute和上面的文章上的文档。可以说,如果您考虑捕获这些类型的异常,绝对值得一读。


12
HandleProcessCorruptedStateExceptions在.Net 4.5中为我工作。
deerchao

2
谢谢villecoder,您是一颗宝石!我已经解决这个问题好几个星期了,试图解决根本问题,最后辞职去治疗症状。您的解决方案是完美的。
gadildafissh

19
!请注意:强烈建议在AccessViolationException之后将其终止,该过程是Corrupted State Exception(CSE)。否则会导致更严重的错误。
Zbigniew Wiadro

6
谢谢,这确实很有帮助,尽管起初我觉得我需要完成所有3个步骤才能捕获这些异常,而实际上这OR是执行这些方法的“逻辑”。:)
Lou

@deerchao我希望您已阅读答案中提供的第一个链接。处理CSE异常不是一个好主意。
像素

17

在配置文件中添加以下内容,它将在try catch块中被捕获。小心提示...尝试避免这种情况,因为这意味着某种违规行为正在发生。

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

2
对于使用c ++ / cli作为dll的用户,应将代码添加到顶部的.exe项目中。
Felix

9

根据以上答案进行编译,为我工作,并按照以下步骤进行了捕获。

步骤#1-将以下代码段添加到配置文件

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

第2步

添加-

[HandleProcessCorruptedStateExceptions]

[SecurityCritical]

在您绑定的函数顶部,捕获异常

来源:http : //www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html


根据msdn.microsoft.com/en-us/library/…,SecurityCriticalAttribute等效于对完全信任的链接需求。我认为所描述的问题并不需要完全信任。
杰里米

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.