是否可以捕获 .NET 中的访问冲突异常?
我可以采取什么措施来捕获 AccessViolationException
吗?它是由我无法控制的非托管 DLL 引发的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我可以采取什么措施来捕获 AccessViolationException
吗?它是由我无法控制的非托管 DLL 引发的。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(5)
正如其他人指出的那样,您不应该“处理”这种情况,但在开发过程中,为了排除故障可以很方便地捕获这种情况。
您可以使用 System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions 属性标记托管方法:
As others pointed out, you shouldn't "handle" this condition, but during development it is handy to catch this for the sake of troubleshooting.
You can mark your managed method with the
System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions
attribute:在您的 App.confg 中,将以下代码放入
标记中:现在您应该能够像捕获其他异常一样捕获损坏的状态异常 (CSE)。
注意:如果您已经有运行时标记,则只需向其添加
以上适用于 .Net 4.5
In your App.confg, plop the following code within the
<configuration>
tag:Now you should be able to catch corrupted state exceptions (CSE) like any other.
Note: If you already have a runtime tag then simply add
<legacyCorruptedStateExceptionsPolicy enabled="true"/>
to itThe above works for .Net 4.5
首先我完全确认 0xA3。但如果没有办法,你可以将脏的非托管 dll 包装在自己的进程中,并通过 IPC(TCP/IP、namedpipes 等)传输数据。捕获所有异常并通知主机进程。因此,您的主机进程基本上不会受到内存损坏的影响。
First of all I fully ack with 0xA3. But if there is no way out you can wrap the dirty unmanaged dll in its own process and transfer data via IPC (TCP/IP, namedpipes, etc.). Catch all exceptions and inform the host-process. So your host-process is mostly save from memory corruption.
您可以使用 try-catch 块包装对非托管 DLL 的调用。 AccessViolationExceptions 可以正常捕获。执行以下代码会显示两条消息:
编辑: .NET 4 引入了 行为发生变化,除非您特别"询问" 运行时执行此操作。
you can wrap the call to the unmanaged DLL with a try-catch block. AccessViolationExceptions can be caught normally. Executing the following code shows both messages:
Edit: .NET 4 introduced a change in behavior, it is no longer possible to catch corrupted state exceptions unless you specifically "ask" the runtime to do so.
你不应该。访问冲突是一个严重的问题:它是对无效内存地址进行写入(或读取)的意外尝试。正如 John 已经澄清的那样,在引发访问冲突之前,非托管 DLL 可能已经损坏了进程内存。这可能会对当前流程的任何部分产生不可预测的影响。
最安全的做法是通知用户,然后立即退出。
更多详细信息:访问冲突是操作系统异常(所谓的 SEH 或结构化异常处理异常)。这是与 System.Exception 中的托管 CLR 异常不同的异常类型。您很少会在纯托管代码中看到 SEH 异常,但如果发生,例如在非托管代码中,CLR 会将其传递到托管代码,您也可以在托管代码中捕获它1。
然而,捕获 SEH 异常大多不是一个好主意。更多详细信息请参阅文章处理损坏的状态异常 在 MSDN 杂志中,以下文本摘自:
1在 .NET 3.5 之前都是如此。在 .NET 4 中,行为已更改。如果您仍然希望能够捕获此类异常,则必须将
legacyCorruptedStateExceptionsPolicy=true
添加到 app.config。更多详细信息请参阅上面链接的文章。You shouldn't. An access violation is a serious problem: it is an unexpected attempt to write to (or read from) an invalid memory address. As John already clarified, the unmanaged DLL might already have corrupted the process memory before the access violation has been raised. This can have unpredicted effects on any part of the current process.
The safest thing to do is to possibly inform the user and then immediately exit.
Some more details: An access violation is an OS exception (a so-called SEH or structured exception handling exception). This is a different kind of exception than the managed CLR exceptions from
System.Exception
. You will rarely see SEH exceptions in purely managed code, but if one occurs, e.g. in unmanaged code, the CLR will deliver it to managed code where you are also able to catch it1.However, catching SEH exceptions is mostly not a good idea. Further details are explained in the article Handling Corrupted State Exceptions in MSDN magazine where the following text it taken from:
1This was true until .NET 3.5. In .NET 4 the behavior has been changed. If you still want to be able to catch such kind of exceptions you would have to add
legacyCorruptedStateExceptionsPolicy=true
to the app.config. Further details in the articled linked above.