C# try/catch 噩梦

3

我有一个应用程序,其代码与此类似(不是我编写的)

try
{
    EnumerateSomeCoolHardwareDevice();
}
catch (Exception ex)
{

} 

更新 - 这是.NET C#,而 EnumerateSomeCoolHardwareDevice() 正在使用 SerialPort?

我知道这段代码很糟糕,但它有其原因!

我的问题是:我可以看到它在 EnumerateSomeCoolHardwareDevice(); 中崩溃,但它没有被 catch (...) 捕获 - 它只是崩溃并出现发送报告对话框!目前这种情况仅发生在发布版本中... 是否有任何原因导致我的异常不会被 catch (...) 捕获?


5
请告诉我们您正在使用哪种语言,这可能有助于回答您的问题,因为涉及到的运行时系统会对答案产生影响。 - Timo Geusch
抱歉,已更新问题说明为 C#(.NET)。 - rudigrobler
有可能 EnumerateSomeCoolHardwareDevice() 调用了 Environment.FailFast (http://msdn.microsoft.com/en-us/library/ms131100.aspx) 这个方法,这可能是问题的原因。你可以将一些数据附加到应用程序日志中,以输出到可用文件中进行检查。 - RCIX
串口访问的是什么?它是物理COM端口还是虚拟COM端口? - Alistair Evans
尝试这个: 尝试{ } 捕获(){} // 这应该是非CLS兼容异常 或者捕获(Win32Exception winex){} - PRR
12个回答

9

我猜测你的语言/框架没有抛出异常,而是EnumerateSomeCoolHardwareDevice()执行了一些奇怪的操作,导致操作系统杀死了进程。请记住,Java和.NET等框架将硬件细节进行了抽象化处理,因此每当你直接操作硬件时,你可能依赖于非托管资源......无论发生什么问题都可能导致程序崩溃,无论是否使用catch语句。


7

可能的一个原因是EnumerateSomeCoolHardwareDevice()函数使用了线程。如果在线程中抛出异常并且没有在该线程内处理,则会导致应用程序崩溃。以下简单应用程序可以证明我的观点:

    public static void testThread()
    {
        throw new Exception("oh god it's broken");
    }

    static void Main(string[] args)
    {
        try
        {
            Thread thread = new Thread(testThread);
            thread.Start();
            Console.ReadKey(); //Just to make sure we don't get out of the try-catch too soon
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

如果你运行该应用程序,它不会像你期望的那样捕获异常,而是会崩溃并停止运行。

我敢打赌这个人的错误是由此引起的。 - Quibblesome

4

2
假设使用.NET,如果 EnumerateSomeCoolHardwareDevice 通过 PInvoke 使用 Win32 方法(访问硬件)并出现错误,则大多数 Native 方法将返回错误代码。 如果不处理该错误代码,并且无论如何调用另一个本机方法(可能是从失败的调用中使用空输出参数),则严重的本机错误(例如访问错误的内存或类似情况)可能会导致程序直接崩溃,而不会抛出异常。

2

你尝试过使用属性

assembly:RuntimeCompatibility(WrapNonExceptionThrows = true)

它可以将任何非.NET异常包装成System.Exception,这样就可以在你的代码中捕获它了。


1
如果您使用的是 .Net 1.1 版本,请使用无参数 catch 块,例如:
catch{
...
}

在 .Net 2.0 之前,可能存在不派生自 System.Exception 的本机异常。

此外,钩取到应用程序域 未处理异常 事件并查看发生了什么。


1

如果只在生产机器上发生,而不是开发机器,则可能是由于DLL不匹配引起的。请仔细检查所有引用的DLL和框架是否为相同版本。

其次,如果错误不是由EnumerateSomeCoolHardwareDevice()抛出的,则它将使应用程序崩溃,因为异常无法返回堆栈(或者这是我对try/catch的理解),我以前也遇到过这种情况。

最后,微软的错误报告通常允许您检查将发送到MS的内容,这应该让您看到错误发生的位置和原因(假设其中包含可读信息)。

检查事件查看器,因为错误也应记录在那里,并且通常提供有关错误的宝贵详细信息,通过对列出的错误进行一些挖掘,您应该能够跟踪故障。


0

EnumerateSomeCoolHardwareDevice()函数内部可能会有一个try..catch块。

如果异常在此处被捕获并处理,那么除非再次抛出异常,否则外部异常不会被触发。


0
(假设是Java)Error和Exception都是Throwable的子类。例如,如果在EnumerateSomeCoolHardwareDevice()中有一个断言失败,那么你会得到一个Error。

0

我猜测可能发生了堆栈溢出。.NET虚拟机会简单地关闭遇到堆栈溢出的Release构建过程,不会抛出CLR异常。该函数内部可能有一个内部的try/catch语句,以某种方式捕获StackOverflowException,这就是为什么在Debug构建中它没有传播到您的代码的原因。

最简单的方法是制作一个调试版本,附加调试器并指示调试器在抛出任何异常之前中断(在Visual Studio中,选择Debug/Exceptions并选中“Common Language Runtime Exceptions”和可能的其他异常,在cordbg.exe中使用“catch exception”)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接