是否可以捕获 .NET 中的访问冲突异常?

发布于 2024-09-11 08:20:44 字数 81 浏览 6 评论 0 原文

我可以采取什么措施来捕获 AccessViolationException 吗?它是由我无法控制的非托管 DLL 引发的。

Is there anything I can do to catch an AccessViolationException? It is being thrown by a unmanaged DLL that I don't control.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

单身情人 2024-09-18 08:20:45

正如其他人指出的那样,您不应该“处理”这种情况,但在开发过程中,为了排除故障可以很方便地捕获这种情况。

您可以使用 System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions 属性标记托管方法:

[HandleProcessCorruptedStateExceptions]
public void MyMethod()
{
    try
    {
        NaughtyCall();
    }
    catch (AccessViolationException e)
    {
        // You should really terminate your application here
    }
}

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:

[HandleProcessCorruptedStateExceptions]
public void MyMethod()
{
    try
    {
        NaughtyCall();
    }
    catch (AccessViolationException e)
    {
        // You should really terminate your application here
    }
}
伴随着你 2024-09-18 08:20:45

是的。

在您的 App.confg 中,将以下代码放入 标记中:

<runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true"/>
</runtime>

现在您应该能够像捕获其他异常一样捕获损坏的状态异常 (CSE)。

注意:如果您已经有运行时标记,则只需向其添加

以上适用于 .Net 4.5

Yes.

In your App.confg, plop the following code within the <configuration> tag:

<runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true"/>
</runtime>

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 it

The above works for .Net 4.5

一个人练习一个人 2024-09-18 08:20:45

首先我完全确认 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.

椒妓 2024-09-18 08:20:45

您可以使用 try-catch 块包装对非托管 DLL 的调用。 AccessViolationExceptions 可以正常捕获。执行以下代码会显示两条消息:

try
{
    throw new AccessViolationException();
}
catch (Exception e)
{
    MessageBox.Show(e.Message + e.StackTrace, e.Message, MessageBoxButtons.OK, MessageBoxIcons.Error);
}
MessageBox.Show("Still running..");

编辑: .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:

try
{
    throw new AccessViolationException();
}
catch (Exception e)
{
    MessageBox.Show(e.Message + e.StackTrace, e.Message, MessageBoxButtons.OK, MessageBoxIcons.Error);
}
MessageBox.Show("Still running..");

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.

伤痕我心 2024-09-18 08:20:44

你不应该。访问冲突是一个严重的问题:它是对无效内存地址进行写入(或读取)的意外尝试。正如 John 已经澄清的那样,在引发访问冲突之前,非托管 DLL 可能已经损坏了进程内存。这可能会对当前流程的任何部分产生不可预测的影响。

最安全的做法是通知用户,然后立即退出。

更多详细信息:访问冲突是操作系统异常(所谓的 SEH 或结构化异常处理异常)。这是与 System.Exception 中的托管 CLR 异常不同的异常类型。您很少会在纯托管代码中看到 SEH 异常,但如果发生,例如在非托管代码中,CLR 会将其传递到托管代码,您也可以在托管代码中捕获它1

然而,捕获 SEH 异常大多不是一个好主意。更多详细信息请参阅文章处理损坏的状态异常 在 MSDN 杂志中,以下文本摘自:

CLR 始终使用与程序本身引发的异常相同的机制将 SEH 异常传递给托管代码。只要代码不尝试处理它无法合理处理的异常情况,这就不是问题。大多数程序在访问冲突后无法安全地继续执行。不幸的是,CLR 的异常处理模型始终鼓励用户通过允许程序捕获 System.Exception 层次结构顶部的任何异常来捕获这些严重错误。但这很少是正确的做法。

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:

The CLR has always delivered SEH exceptions to managed code using the same mechanisms as exceptions raised by the program itself. This isn't a problem as long as code doesn't attempt to handle exceptional conditions that it cannot reasonably handle. Most programs cannot safely continue execution after an access violation. Unfortunately, the CLR's exception handling model has always encouraged users to catch these serious errors by allowing programs to catch any exception at the top of the System.Exception hierarchy. But this is rarely the right thing to do.

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 legacyCorruptedState­­ExceptionsPolicy=true to the app.config. Further details in the articled linked above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文