在.NET应用程序中显式导致AccessViolationException

时间:2016-12-28 08:32:36

标签: c# .net

我在一个相当大的.NET应用程序中调试一个讨厌的AccessViolationException(一个取消整个过程,只留下一个事件查看器条目)。在该应用程序中发生了令人分心的事情很多,这使得根本原因分析非常困难。我想要一个玩具问题"版本,但在(最好)生成C ++,我很难创建一个死于这种例外的.NET应用程序。

我已搜索并找到例如this somewhat old post,其中显示的代码应该抛出我想要的异常。但如果我编译这个:

static unsafe void Main(string[] args)
{
    Console.WriteLine("Doing stuff");

    try
    {
        int foo = (*((int*)0));
    }
    catch (AccessViolationException)
    {
        Console.WriteLine("Don't want to reach this.");
    }

    Console.WriteLine("Waiting");
    Console.ReadKey();
}

或者这个:

static unsafe void Main(string[] args)
{
    Console.WriteLine("Doing stuff");

    try
    {

        int foo;
        int* ip = null;
        foo = *ip; //crash!
    }
    catch (AccessViolationException)
    {
        Console.WriteLine("Don't want to reach this.");
    }

    Console.WriteLine("Waiting");
    Console.ReadKey();
}

PS。 catch块就在那里,因为我尝试表示的实际场景是我无法捕捉到异常的场景(所以我自己不能throw

使用"允许不安全的代码"选项打开,在新的.NET控制台应用程序中,它崩溃时出现空引用异常,而不是AccessViolationException。虽然我并不是太惊讶,并且有点理解为什么会这样,但我仍然留下原来的问题。

底线::是否有一种简单的方法可以创建一个导致AccessViolationException按需的.NET应用程序,最好是在没有异常选项的情况下进程完全死亡的方式处理,只在事件查看器中留下痕迹?

3 个答案:

答案 0 :(得分:5)

0(或null)替换为-1 - 它应触发所需的行为,因为 -1 ,当隐式转换为指针时,会导致 0xFFFFFFFF ... 通常属于内核模式地址空间(在Windows和* nix中),不允许您从用户模式程序中读取。

答案 1 :(得分:2)

另外,如果您不想使用"不安全"在C#中,您可以在解决方案中创建简单的C ++ CLR项目,并使用内存和其他资源执行所需的一切。 ))

using namespace System;
namespace ClassLibrary1 {

public ref class Class1
{
    // TODO: Add your methods for this class here.
public:
    void ThrowException()
    {
        int * p = (int*)-1;
        *p = 10;
    }
};

}

此方法为我们提供了AccessViolationException。

答案 2 :(得分:0)

同事想出了一个甚至不需要unsafe代码的版本:

using System;
using System.Runtime.InteropServices;
using static System.Console;

class Program
{
    static void Main(string[] args)
    {
        WriteLine("Doing stuff");

        try
        {
            Marshal.StructureToPtr(1, new IntPtr(1), true);
        }
        catch (AccessViolationException)
        {
            WriteLine("Should not reach this.");
        }
        finally
        {
            WriteLine("Should not reach even this.");
        }

        WriteLine("Waiting");
        ReadKey();
    }
}

try块语句将终止整个事件,不会执行其他代码,甚至不会执行finally块。