检测到AccessViolationException时如何强制应用程序崩溃 [英] How to force an application crash when AccessViolationException is detected

查看:315
本文介绍了检测到AccessViolationException时如何强制应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用自动崩溃报告工具(即 http://crashrpt.sourceforge.net )来生成崩溃报告。



因此,如果一段非托管代码通过访问 NULL 指针失败,例如应用程序崩溃,崩溃报告工具激活,我们可以获得可用的堆栈跟踪来诊断和分组问题。



问题是.NET在某些情况下似乎会干扰崩溃处理。一个示例如下:

  this.Dispatcher.BeginInvoke((ThreadStart)delegate 
{
/ / send message to unmanaged control for perform a specific task。
User32.SendMessage(...);
},DispatcherPriority.Input);

如果非托管组件因访问冲突而失败,则内部.NET方法捕获实际应该是什么崩溃为 AccessViolationException 并重新包装在一个 TargetInvocationException 中,然后崩溃(它不会这样做,而不使用方法调用)



这是非常不方便的,因为本机堆栈信息完全丢失。剩下的是以下堆栈,与非托管部分失败的位置无关:

  kernelbase!RaiseException + 0x6c 
clr!RaiseTheExceptionInternalOnly + 0x276
clr!RaiseTheException + 0x86
clr!RaiseTheExceptionInternalOnly + 0x30a
clr!RealCOMPlusThrow + 0x2f
clr!ThrowInvokeMethodException + 0xac
clr!RuntimeMethodHandle :: InvokeMethod + 0xa64
mscorlib_ni + 0x2d37b1
mscorlib_ni + 0x2cf92a
windowsbase_ni + 0xd77b1
windowsbase_ni + 0xd768a
windowsbase_ni + 0xc2d5c
windowsbase_ni + 0xc2c98
mscorlib_ni + 0x302346
mscorlib_ni + 0x302301
windowsbase_ni + 0xc2b9b
windowsbase_ni + 0xd640b
windowsbase_ni + 0xd65ca
windowsbase_ni + 0xd798b
windowsbase_ni + 0xd78db
windowsbase_ni + 0xd7756
windowsbase_ni + 0xd768a
windowsbase_ni + 0xd5cae
windowsbase_ni + 0xd71e1
user32!InternalCallWinProc + 0x23
user32!UserCallWinProcCheckWow + 0x100
user32!DispatchMessageWorker + 0x3ef
user32!D ispatchMessageW + 0x10
windowsbase_ni + 0xddca8
windowsbase_ni + 0xd5636
windowsbase_ni + 0xd5325
windowsbase_ni + 0xb27d3
presentationframework_ni + 0x2721b7
presentationframework_ni + 0x271e0f
presentationframework_ni + 0x271baa
clr!CallDescrWorkerInternal + 0x34
clr!CallDescrWorkerWithHandler + 0x6b
clr!MethodDescCallSite :: CallTargetWorker + 0x152
clr!RunMain + 0x1aa
clr!Assembly :: ExecuteMainMethod + 0x124
clr!SystemDomain :: ExecuteMainMethod + 0x614
clr!ExecuteEXE + 0x4c
clr!_CorExeMainInternal + 0xdc
clr!_CorExeMain + 0x4d
mscoreei!_CorExeMain + 0x10a
mscoree!ShellShim__CorExeMain + 0x7d
mscoree!_CorExeMain_Exported + 0x8
kernel32!BaseThreadInitThunk + 0xe
ntdll!__ RtlUserThreadStart + 0x72
ntdll!_RtlUserThreadStart + 0x1b

如果非托管组件发生故障,我们如何防止这种情况并强制应用程序立即崩溃?

解决方案

尝试thi s:

  this.Dispatcher.BeginInvoke((Action)delegate 
{
User32.SendMessage(。 ..);
},DispatcherPriority.Input);

应用程序应该按照您想要的方式崩溃。






我看到的大多数示例都是使用匿名委托调用 Dispatcher.BeginInvoke()








为什么会这样?



似乎是CLR代码,方式在$ System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback,Object args,Int32 numArgs)中$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b在MS.Intern al.Threading.ExceptionFilterHelper.TryCatchWhen(Object source,Delegate method,Object args,Int32 numArgs,Delegate catchHandler)
在System.Windows.Threading.DispatcherOperation.InvokeImpl()

直接调用 Action ,大多数其他代理都使用反射来调用。



反射机制将在 TargetInvocationException 中包装异常。



请参阅这个答案给另一个问题解释。






其他不会包装异常的特殊情况代理是:
DispatcherOperationCallback SendOrPostCallback 虽然要工作,他们必须用一个参数调用。

  this.Dispatcher.BeginInvoke(DispatcherPriority.Input,
(SendOrPostCallback)(delegate(object o)
{
throw new AccessViolationException(o.ToString ());
}),test);


We use an automated crash reporting tool (namely http://crashrpt.sourceforge.net) for generating crash reports.

So if a piece of unmanaged code fails by accessing a NULL pointer for example, the application crashes, the crash reporting tool activates and we get usable stack trace for diagnosing and grouping issues.

The problem is that .NET seems to interfere with crash handling in some cases. One sample is the following:

this.Dispatcher.BeginInvoke((ThreadStart)delegate
{
  // Send message to unmanaged control for performing a specific task.
  User32.SendMessage(...);
}, DispatcherPriority.Input);

If the unmanaged component then fails with an access violation, internal .NET methods catch what should actually be a crash as AccessViolationException and rewrap it inside a TargetInvocationException first, then crashes (it would not do that without using method invocation).

This is highly inconvenient, because the native stack information is completely lost. What remains is the following stack, independently of where exactly the unmanaged part has failed:

kernelbase!RaiseException+0x6c
clr!RaiseTheExceptionInternalOnly+0x276
clr!RaiseTheException+0x86
clr!RaiseTheExceptionInternalOnly+0x30a
clr!RealCOMPlusThrow+0x2f
clr!ThrowInvokeMethodException+0xac
clr!RuntimeMethodHandle::InvokeMethod+0xa64
mscorlib_ni+0x2d37b1
mscorlib_ni+0x2cf92a
windowsbase_ni+0xd77b1
windowsbase_ni+0xd768a
windowsbase_ni+0xc2d5c
windowsbase_ni+0xc2c98
mscorlib_ni+0x302346
mscorlib_ni+0x302301
windowsbase_ni+0xc2b9b
windowsbase_ni+0xd640b
windowsbase_ni+0xd65ca
windowsbase_ni+0xd798b
windowsbase_ni+0xd78db
windowsbase_ni+0xd7756
windowsbase_ni+0xd768a
windowsbase_ni+0xd5cae
windowsbase_ni+0xd71e1
user32!InternalCallWinProc+0x23
user32!UserCallWinProcCheckWow+0x100
user32!DispatchMessageWorker+0x3ef
user32!DispatchMessageW+0x10
windowsbase_ni+0xddca8
windowsbase_ni+0xd5636
windowsbase_ni+0xd5325
windowsbase_ni+0xb27d3
presentationframework_ni+0x2721b7
presentationframework_ni+0x271e0f
presentationframework_ni+0x271baa
clr!CallDescrWorkerInternal+0x34
clr!CallDescrWorkerWithHandler+0x6b
clr!MethodDescCallSite::CallTargetWorker+0x152
clr!RunMain+0x1aa
clr!Assembly::ExecuteMainMethod+0x124
clr!SystemDomain::ExecuteMainMethod+0x614
clr!ExecuteEXE+0x4c
clr!_CorExeMainInternal+0xdc
clr!_CorExeMain+0x4d
mscoreei!_CorExeMain+0x10a
mscoree!ShellShim__CorExeMain+0x7d
mscoree!_CorExeMain_Exported+0x8
kernel32!BaseThreadInitThunk+0xe
ntdll!__RtlUserThreadStart+0x72
ntdll!_RtlUserThreadStart+0x1b

How can we prevent that and force the application to crash immediately when the unmanaged component fails?

解决方案

Try this:

this.Dispatcher.BeginInvoke((Action) delegate 
{
    User32.SendMessage(...);
}, DispatcherPriority.Input);

The application should crash the way you want it to.


Most of the examples I've seen that call Dispatcher.BeginInvoke() with an anonymous delegate use an Action.


Why does this happen?

It seems that the CLR code, way down in:

at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()

invokes an Action directly, most other delegates are invoked using reflection.

The reflection mechanism will wrap exceptions in a TargetInvocationException.

See this answer to another question to explain.


Other special case delegates which will not wrap exceptions are: DispatcherOperationCallback and SendOrPostCallback, though to work they have to be called with a single argument.

this.Dispatcher.BeginInvoke(DispatcherPriority.Input,
    (SendOrPostCallback)(delegate(object o)
    {
        throw new AccessViolationException(o.ToString());
    }), "test");

这篇关于检测到AccessViolationException时如何强制应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆