【问题标题】:How to make C# application crash with an AccessViolationException如何使用 AccessViolationException 使 C# 应用程序崩溃
【发布时间】:2019-05-30 21:14:18
【问题描述】:

如何在 c# 中故意使带有AccessViolationException 的应用程序崩溃?

我有一个使用非托管 DLL 的控制台应用程序,该应用程序最终由于访问冲突异常而崩溃。因此,我需要故意抛出一个AccessViolationException 来测试它在某些情况下的行为。

除此之外,它必须特别是 AccessViolationException,因为这个异常不是由 catch 块处理的。

令人惊讶的是,这不起作用:

public static void Crash()
{
    throw new AccessViolationException();
}

这都不是:

public static unsafe void Crash()
{
    for (int i = 1; true; i++)
    {
        var ptr = (int*)i;
        int value = *ptr;
    }
}

【问题讨论】:

  • 如果我正确理解文档 --> 默认情况下,公共语言运行时 (CLR) 不会将这些异常传递给托管代码,并且 try/catch 块(和其他异常处理子句)不为他们调用。如果您绝对确定要保持对这些异常的处理,则必须将HandleProcessCorruptedStateExceptionsAttribute 属性应用于要执行其异常处理子句的方法
  • 第二个 sn-p 肯定是在正确的轨道上。但是使用*(int*)0x10000 = 0;生成AVE而不是NRE,0x10000以下的地址被认为是由空指针引起的。
  • @HansPassant,你能解释一下为什么是 10000 吗?它只是远离保留内存的随机值吗?
  • 很多历史,可以追溯到 Windows NT,第一个 32 位版本的 Windows。他们非常担心程序员不会正确地移植他们的 16 位程序。通过使 0x10000 以下的所有内存都无法访问,它们可以生成有用的诊断信息。当程序访问对象的字段时,空指针还可以生成对非 0 地址的内存访问。 C# 有一个很好的保证,它不会导致误导性异常,它生成的代码会在对对象进行任何操作之前检查对象的地址。

标签: c# access-violation


【解决方案1】:

确定性方法是让 Windows 为您抛出它:

来自 Петър Петров 的回复:How to make C# application crash

[DllImport("kernel32.dll")]
static extern void RaiseException(uint dwExceptionCode, uint dwExceptionFlags,  uint nNumberOfArguments, IntPtr lpArguments);

void start()
{
    RaiseException(0xC0000005, 0, 0, new IntPtr(1));
}

【讨论】:

    【解决方案2】:

    这是“原生”方式——尽管@Storm 方法是 100% 确定性的。技巧是尝试写入远离当前指针的内存。 IE。即使我在我的程序中分配了 4 个字节,接下来的几千字节仍然在为我的程序保留的内存部分中。远射,你应该能得到它。

    int[] array = new int[1];
    fixed (int* ptr = array)
    {
          ptr[2000000] = 42;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-04
      • 1970-01-01
      • 2011-03-03
      • 2013-08-18
      • 1970-01-01
      • 1970-01-01
      • 2018-02-12
      • 2012-05-20
      相关资源
      最近更新 更多