首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >应用程序部分崩溃?如何捕获无法捕获的异常?

应用程序部分崩溃?如何捕获无法捕获的异常?
EN

Stack Overflow用户
提问于 2010-07-27 15:34:34
回答 3查看 4.5K关注 0票数 10

我有一个用C#编写的程序,在Windows CE设备(在Compact Framework上)上运行。它处理最少的用户操作(按钮点击),使用串行端口和TCP/IP通信。

问题是有时软件会自动关闭。在后台,应用程序(或应用程序的一部分)似乎仍在运行(至少在一个文档记录的情况下是这样),因为它使用串行端口,所以重启应用程序没有任何帮助。我不能重现这个问题,因为它发生在大多数情况下,没有用户交互,没有串口通信,网络通信都是“我还活着”消息,软件似乎无缘无故地崩溃了。(我尝试让它在调试模式下发生,以便至少知道代码中的问题在哪里,如果它是一个软件错误,但到目前为止我还没有运气。)

因为我已经没有想法了,所以问题是:什么bug或异常、操作系统操作或硬件故障会导致这种行为?

在同一类型的不同设备上都发现了这个问题,所以它不应该是硬件错误。(或者我的所有硬件都有相同的错误。)异常是被处理的,所以它不应该是异常。未处理的异常也会被处理,所以它也不应该是未处理的异常。(我的猜测是它是由StackoverflowException引起的,因为我不知道有任何其他无法捕获的异常,但是代码中没有递归,至少不是自愿的,所以它也不应该是可能的。)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-27 15:44:32

相当多的异常不能被捕获,这些异常在不同的.NET版本和.NET版本中是不同的。一些异常可以被捕获和记录,但不能恢复(内存异常)。然而,调试它们是可能的(它们被称为,第一次机会总是调试器的,第二次机会是代码的,感谢JeroenH指出这一点)。这里有一个post at CodeProject that explains this原则。

您应该做的是在Visual Studio中选择一些您怀疑可能发生的候选异常,并将调试器附加到正在运行的实例。

拥有非托管资源(串行端口)意味着您可能会有非托管泄漏(未正确使用IDisposable + using )和非托管异常。这些异常只能在try/catch块中使用空catch (即,没有指定even Exception,它不是非托管异常的父级)来捕获。

PS:当在finally块或finalizer/destructor中引发异常时,可能会发生一些未定义的行为。此外,跨越线程边界传播并终止所有线程的异常也不多。

编辑

为了让事情更清楚一些,有一些例外情况是CLR (及其规范)定义为不可捕获的。基本上,这些都是跨越线程边界的异常。当这些异步异常发生在锁中时,将导致状态损坏。最著名的是OutOfMemoryExceptionThreadAbortExceptionStackOverflowException。当OutOfMemoryExceptionStackOverflowException出现在同步代码中时,您不太可能纠正状态,CLR将终止您的应用程序。

此外,还有ExecutionEngineExceptionBadImageFormatException,它们不应该出现在可验证的代码中,也不应该被捕获。像TypeLoadExceptionMissingMemberException这样的异常有时可以捕获,有时不能捕获(如果缺少链接的程序集,则很难捕获这些异常,而且您不应该捕获这些异常,但是如果使用反射,则应该捕获这些异常)。

简而言之:异常应该在它们发生的线程中被捕获。如果异常发生在另一个线程中,您将无法捕获它们,因为它们不会被传播(ThreadAbortException除外)。您的应用程序在发生异常后仍然存活(至少,您认为是这样的),因此假设异常不会发生在您试图捕获它的线程中是合乎逻辑的。使用Debug > Exceptions窗口,您可以选择任何异常,并在发生异常时中断代码。

关于异常的说明

添加了有关托管和非托管异常的说明。由于非托管异常不是从Exception继承的,因此无法使用catch (Exception e)捕获非托管异常。相反,使用一个空的catch,它将为您捕获任何非托管异常。将其封装在您的应用程序和线程入口点方法中,您应该能够捕获大多数可捕获的异常。

票数 10
EN

Stack Overflow用户

发布于 2010-07-27 22:29:40

您可能有一个本机异常或访问冲突(通常表现为第一次机会异常)。任何数量的托管异常处理都无法捕获其中的一个-关键是不要在一开始就导致异常。

您是否正在调用或进行不安全的调用?如果你正在调用一个API,并导致缓冲区溢出或堆栈损坏之类的事情,你会看到这种行为(尽管你经常会得到一个操作系统对话框抱怨。

追踪这些通常是很困难的。这是一个CE设备-它有调试端口(通常是串行端口)吗?异常很可能会在那里转储一条消息,所以如果您可以访问一个异常,这是一个很好的起点。如果你有KITL,在应用程序运行的同时运行调试中的操作系统也可能会捕获正在发生的事情。

票数 3
EN

Stack Overflow用户

发布于 2010-07-27 15:47:53

如果您使用Thread类启动辅助线程,并且没有指定它们是后台线程,那么它们将使您的进程保持运行,直到它们退出,即使主线程已经完成(即。main窗体已关闭,Main方法已返回。)

如果你有一个StackOverflowException,你的进程就会被Windows直接杀死,所以这不是它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3341534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档