我在一个相当大的.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应用程序,最好是在没有异常选项的情况下进程完全死亡的方式处理,只在事件查看器中留下痕迹?
答案 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
块。