C#偶尔的AccessViolationException

时间:2015-03-29 10:37:21

标签: c#

我有第三方库,有时会导致AccessViolationException。我已经标记了罪魁祸首。我真的很喜欢这种方法优雅地失败,这样我的调用代码可以在短时间内再次尝试,但此时,这个异常会导致整个应用程序崩溃。

    public static PlayerModel GetModel(int instanceId)
    {
        try
        {
            // New player model.
            PlayerModel model = new PlayerModel();

            // Fill.
            model._flakyLibrary = new FlakyLibrary(instanceId); // **Sometimes crashes**
            model.instanceId = instanceId;

            // Return the new player model.
            return model;
        }
        catch
        {
            // Try again in a bit - the game is not fully loaded.
            return null;
        }
    }

我有一个想法就是开始一个子进程来运行这个逻辑并且如果需要那么优雅地崩溃 - 我不知道如何做到这一点,更不用说有一个进程返回这种对象(我的自定义PlayerModel)到另一个进程。我已经筋疲力尽地搜索Google和Stack Overflow(也许我在问错误的问题?)。

解决方案

非常感谢Theodoros。我已将以下属性添加到上述方法中。现在正在抓住例外。

[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
    [System.Security.SecurityCritical]

P.S - 如果有人知道我应该研究什么,我仍然着迷于了解多重过程解决方案?非常感谢。

另一个编辑: 我找到了使用多个进程的解决方案:NamedPipeServerStream。

1 个答案:

答案 0 :(得分:5)

当您的进程尝试访问不属于自己的内存时,AccessViolationException通常会引发异常。 (顺便提一句,NullReferenceException只是低地址的AccessViolationException,使用不同的名称,以便提示您是什么原因引起的。)因此,说出这一点是合理的。这或多或少是程序内部发生的事情:取消引用无效指针(可能是空指针)或超出特定缓冲区边界的访问。

如果您没有弄乱指针,则代码不对此问题负责。您正在调用的构造函数负责执行不安全和无效的操作。如果您使用的库是开源的,您可以通过查找上述可疑行为,自行进入并尝试自行诊断问题。然后,您可以继续尝试修复它(并可能为该库的开发人员提供修复)。

如果由于任何原因无法完成上述操作,则有一种解决方法。默认情况下,托管代码无法捕获AccessViolationException,因为它是一个损坏的状态异常(CSE),但您可以选择全局处理此类异常(通过应用{{3}中描述的修复})或每个方法(使用another answer属性)。

但是,您必须了解所承担的风险:您的程序将尝试从损坏的状态中恢复。如果可以的话,尽量不要使用强迫你这样做的库。