C# 在单独的线程上捕获AccessViolationException
我正在调用一个可能不稳定的本机库,我想确保我的C应用程序能够经受住潜在的C# 在单独的线程上捕获AccessViolationException,c#,pinvoke,C#,Pinvoke,我正在调用一个可能不稳定的本机库,我想确保我的C应用程序能够经受住潜在的AccessViolationException。我在我的App.config中找到了一种捕获异常的方法。由于崩溃发生在一个我不关心的单独线程上(我不关心它是否死亡),所以让我的应用程序运行安全吗?如果没有,是否有任何机制允许我对本机代码进行沙箱处理以防止崩溃 我不只是想记录崩溃,我真的在努力生存AccessViolationException 我尝试过在另一个AppDomain中执行代码,但没有真正的帮助,因为它在同一个进
AccessViolationException
。我在我的App.config
中找到了一种捕获异常的方法。由于崩溃发生在一个我不关心的单独线程上(我不关心它是否死亡),所以让我的应用程序运行安全吗?如果没有,是否有任何机制允许我对本机代码进行沙箱处理以防止崩溃
我不只是想记录崩溃,我真的在努力生存AccessViolationException
我尝试过在另一个AppDomain
中执行代码,但没有真正的帮助,因为它在同一个进程中运行。我也已经有了一个备份解决方案,它依赖于一个新的进程
,以及一个IPC通道进行通信,但这很难维护和调试。如果我能在主流程中这样做,事情就会简化很多
如果要创建一个测试环境,只需创建一个简单的Win32库,其中包含一个导致崩溃的函数(AccessViolationException
)
C标题:
void do_crash()
{
int *b = NULL;
int c = b[3000];
}
[DllImport("CrashLib.dll", EntryPoint = "do_crash")]
extern static void DoCrash();
static void Main(string[] args)
{
ExecuteSandboxed(delegate
{
DoCrash();
});
// Even if there's a AccessViolationException, I can keep going
Console.ReadLine();
}
private static void ExecuteSandboxed(Action action)
{
try
{
Task.Run(action).Wait();
Console.WriteLine("Success");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
uu declspec(dllexport)void do_crash()代码>
C来源:
void do_crash()
{
int *b = NULL;
int c = b[3000];
}
[DllImport("CrashLib.dll", EntryPoint = "do_crash")]
extern static void DoCrash();
static void Main(string[] args)
{
ExecuteSandboxed(delegate
{
DoCrash();
});
// Even if there's a AccessViolationException, I can keep going
Console.ReadLine();
}
private static void ExecuteSandboxed(Action action)
{
try
{
Task.Run(action).Wait();
Console.WriteLine("Success");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
C#来源:
void do_crash()
{
int *b = NULL;
int c = b[3000];
}
[DllImport("CrashLib.dll", EntryPoint = "do_crash")]
extern static void DoCrash();
static void Main(string[] args)
{
ExecuteSandboxed(delegate
{
DoCrash();
});
// Even if there's a AccessViolationException, I can keep going
Console.ReadLine();
}
private static void ExecuteSandboxed(Action action)
{
try
{
Task.Run(action).Wait();
Console.WriteLine("Success");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
简而言之,例外情况
异常背后最基本的想法是说“这无法完成”,并防止应用程序继续处于损坏状态。当引发异常时,它通常允许应用程序当前情况并继续执行。这是通过倒带调用堆栈并查找异常处理程序(try-catch
blocks)来完成的
例外情况可能来自3个主要来源:
- 应用程序本身(使用
抛出…
)
- 操作系统异常,例如
FileNotFoundException
- CPU异常,例如
除以零异常
(由于ALU无法执行此类计算而引发)
到目前为止,最可怕的异常是CPU引发的异常,因为它们可以使CPU处于无效状态
此外,例外情况可分为三类:
- 无效操作-当应用程序尝试执行无效操作时,会引发此类异常。诸如访问不存在的文件、除以零等操作
- 无效线程状态-当给定线程的状态损坏时,会引发此类异常。运行时堆栈损坏等情况可能是原因之一
- 无效进程(应用程序)状态-当整个应用程序处于无效状态时,会引发此类异常。内存不足就是一个很好的例子
每种异常都比以前的异常更严重。第一个将终止当前过程并启动调用堆栈倒带。第二个线程将终止整个线程。最后一个将终止整个应用程序
注意:终止过程要复杂得多,例外情况并没有真正分为三类
理解AccessViolationException
现在我们已经对异常有了基本的了解,我们可以预测AccessViolationException
将使我们的应用程序处于何种状态
首先,谁抛出异常?这是一个有点诡计的问题*但实际上,当操作系统意识到地址尚未分配给进程时,就会抛出异常
这是什么类型的异常?因为异常与线程或应用程序的状态无关;我们只是试图访问“不存在的”内存(就像我们可能试图访问不存在的文件一样)。这显然是一个无效操作
异常
AccessViolationException
是操作系统中的一个无效操作异常。现在我们知道,只要我们确定没有使CPU状态、应用程序状态或线程状态无效,就可以安全地继续执行;我们只是试图做一些非法的事情。@Isun我知道如何处理它们,我想知道继续这样做是否安全,如果不安全,是否还有其他方法可以继续安全。文章()详细解释了这个想法,但总的来说,继续这样做是安全的,因为主线程的堆栈将保持干净。与OutOfMemoryException
不同,AccessViolationException
对整个应用程序来说不是致命的。非常好!你应该将此作为答案发布。。