Как проверить обработку AccessViolationException


Мне нужно написать тест, который проверяет, что мой код может обрабатывать исключение AccessViolationException (или любое другое исключение поврежденного состояния WIN32-CSE), которое происходит в небезопасном контексте, обычно вызывая сторонний lib. Все это должно быть сделано с помощью C# на .net 4.0.

Я нашел этот связанный Вопрос Как обрабатывать 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());
    }
}
Есть ли у кого-нибудь предложение о том, как достичь этого без большого труда (напр. запись небезопасного lib, который вызывает это исключение).

С уважением

Обновлено: чтобы соответствовать моему окончательному решению, спасибо 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();
        }
    }
}
2 15

2 ответа:

Попробуйте следующее

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

Это не гарантировано, чтобы бросить AccessViolationException спецификацией CLI, но это будет на каждой платформе, о которой я знаю

    private static unsafe void AccessViolation()
    {
        int* p = (int*)0xFF004324;
        int q = *p;
    }

Отредактировал небезопасную запись. Чтение с этого адреса все равно должно генерировать исключение AccessViolationException, если только оно случайно не находится в вашем адресном пространстве.