【问题标题】:How to test handling of AccessViolationException如何测试 AccessViolationException 的处理
【发布时间】:2012-06-06 01:34:04
【问题描述】:

我需要编写一个测试来验证我的代码是否可以处理在不安全的上下文中发生的 AccessViolationException(或任何其他 WIN32 损坏状态异常 - CSE),通常通过调用第 3 方库。 这一切都应该在 .net 4.0 上使用 C# 完成。

我发现了这个相关的问题How to handle AccessViolationException 和这篇相关的文章http://dotnetslackers.com/articles/net/All-about-Corrupted-State-Exceptions-in-NET4.aspx,其中解释了如何捕捉这些 CSE 及其背景。

所以我想在测试中激发一个 WIN32 CSE,以确保在我的应用程序中正确处理。比如:

一些要测试的示例类:

public class MyExceptionHandler
{
    [HandleProcessCorruptedStateExceptions]
    public void HandleCorruptedStateException()
    {
        try
        {
             //Force genuine unsafe AccessViolationException
             //not just a throw new AccessViolationException
        }
        catch(Exception e)
        {
             //Log/cleanup/other
        }
    }

    public void DoesNotHandleCorruptedStateException()
    {
        try
        {
             //Force genuine unsafe AccessViolationException
             //not just a throw new AccessViolationException
        }
        catch (Exception e)
        {
            //Log/cleanup/other
        }
    }
}

测试:

class MyTest
{
    [Test]
    public void ShouldVerifyThatAnAccessViolationExceptionIsHandledCorrectly()
    {
        var handler = new MyExceptionHandler();

        Assert.DoesNotThrow(() => handler.HandleCorruptedStateException());
    }

    [Test]
    public void ShouldVerifyThatAnAccessViolationExceptionIsNotHandledCorrectly()
    {
        var handler = new MyExceptionHandler();

        Assert.Throws<AccessViolationException>(() => handler.DoesNotHandleCorruptedStateException());
    }
}

有没有人建议如何在不做太多工作的情况下实现这一目标(例如,编写导致此异常的不安全库)。

亲切的问候

更新:为了匹配我的最终解决方案,感谢 JaredPar。

public class MyExceptionHandler
{
    [HandleProcessCorruptedStateExceptions]
    public void HandleCorruptedStateException()
    {
        try
        {
            var ptr = new IntPtr(42);
            Marshal.StructureToPtr(42, ptr, true);
        }
        catch(Exception e)
        {
             //Log/cleanup/other
        }
    }

    public void DoesNotHandleCorruptedStateException()
    {
        try
        {
            var ptr = new IntPtr(42);
            Marshal.StructureToPtr(42, ptr, true);
        }
        catch (Exception e)
        {
            //Log/cleanup/other
        }
    }
}

提示: 要手动验证这一点,请使用简单的控制台应用程序,从命令行:

class Program
{
    static void Main(string[] args)
    {
        var handler = new MyExceptionHandler();

        if (args.Length > 1)
        {
            handler.HandleCorruptedStateException();
        }
        else
        {
            handler.DoesNotHandleCorruptedStateException();
        }
    }
}

【问题讨论】:

    标签: c# .net c#-4.0 access-violation unsafe


    【解决方案1】:
        private static unsafe void AccessViolation()
        {
            int* p = (int*)0xFF004324;
            int q = *p;
        }
    

    编辑了不安全的写入。从该地址读取仍应生成 AccessViolationException,除非巧合的是在您的地址空间内。

    【讨论】:

    • OP 要求提供不涉及不安全代码的 C# 答案
    【解决方案2】:

    试试下面的

    var ptr = new IntPtr(42);
    Marshal.StructureToPtr(42, ptr, true);
    

    CLI 规范不保证会抛出AccessViolationException,但它会在我知道的每个平台上发生

    【讨论】:

    • 谢谢,但这不会生成 CSE,只会生成 ArgumentNullException。它必须是真正的 Win32 CSE,如果未在 try catch 中处理会导致应用程序崩溃 + 标有 [HandleProcessCorruptedStateExceptions] 属性等,如文章中所述。
    • 我的立场是正确的。这确实有效:-D。我在测试中犯了一个错误(典型)。非常感谢你:)。
    猜你喜欢
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多