Exception handling CLR是如何识别“a”的;损坏状态异常“;?
背景 我们的应用程序调用一个混合模式程序集,该程序集的非托管代码中存在一个已知错误,导致抛出AccessViolationException 我们的目标是捕获AV异常,将其包装,并在终止应用程序之前抛出一个新的异常,该异常将在堆栈的更高层被捕获并记录 问题 我们的代码没有按我们预期的那样运行。。。我们用来包装AV异常的“普通”异常的行为就像CSE一样,没有被我们的顶级异常处理程序捕获。相反,它冒泡到操作系统,从而终止了进程。这只在Windows事件日志中留下了一条混乱的日志消息,表明InvalidOperationException以某种方式绕过了所有异常处理程序并终止了进程 注意,只有将AV异常设置为包装异常上的内部异常时,才会显示此行为 以下是一个例子:Exception handling CLR是如何识别“a”的;损坏状态异常“;?,exception-handling,clr,Exception Handling,Clr,背景 我们的应用程序调用一个混合模式程序集,该程序集的非托管代码中存在一个已知错误,导致抛出AccessViolationException 我们的目标是捕获AV异常,将其包装,并在终止应用程序之前抛出一个新的异常,该异常将在堆栈的更高层被捕获并记录 问题 我们的代码没有按我们预期的那样运行。。。我们用来包装AV异常的“普通”异常的行为就像CSE一样,没有被我们的顶级异常处理程序捕获。相反,它冒泡到操作系统,从而终止了进程。这只在Windows事件日志中留下了一条混乱的日志消息,表明Invali
[Test]
public void RunTest()
{
try
{
ProvokeAccessViolation();
}
catch (InvalidOperationException e)
{
// We never get here!
Console.WriteLine("Log exception: " + e);
}
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public static void ProvokeAccessViolation()
{
try
{
var ptr = new IntPtr(1);
const bool someValue = true;
Marshal.StructureToPtr(someValue, ptr, true); // Will throw AccessViolationException
}
catch (AccessViolationException ex)
{
Console.WriteLine("Caught AV exception: " + ex);
throw new InvalidOperationException("Wrapping AV exception", ex);
}
}
我的问题是,CLR如何知道将包装器异常(上例中为InvalidOperationException)视为CSE
类似地,如果您只是从托管代码中抛出一个新的AccessViolationException,为什么它的行为不像CSE?(…我假设在这两种情况下使用相同的机制)
更新:
根据Hans的回答,下面是一个屏幕截图,显示了正在抛出和捕获的AV异常:
catch (AccessViolationException ex)
你犯了一个简单的错误,否则可能说明了感染CSE的巨大危险。问题是,您还必须知道要捕获哪个特定的CSE。他们不止一个
是的,这场灾难始于操作系统中的AVE。但并没有保持这种方式,CLR对低64KB内存中的访问触发的AVE有一个特殊规则。它将它们转换为NullReferenceException
。你没抓到。修正:
catch (NullReferenceException ex)
现在它工作正常。谢谢Hans-有趣的信息。。。但是我的机器上没有相同的行为(例如,调用Marshal.StructureToPtr()时肯定会抛出一个AVE)。在最初的示例中,我感兴趣的是为什么它没有捕获RunTest()中的invalidoOperationException。CLR不会将其呈现给catch块,因为它认为它是CSE。如果您将HPCSE属性添加到RunTest,它将按照设计吞下InvalidOperationException。不,它肯定是一个引发的NullReferenceException。只需将其更改为
var ptr=new IntPtr(65536)
获取AccessViolationException。不在我的计算机上:0)…我附上了一个屏幕截图来演示。无论如何,accessViolation()中的catch只能是catch(Exception ex)。我的问题是,为什么你不能在RunTest()中捕捉到InvalidOperationException?我无法重新编程,但没有使用MSTest runner,而是使用了控制台模式的应用程序。请确保在“调试+异常”对话框中关闭了抛出的复选框。