简体   繁体   English

C#尝试/捕捉噩梦

[英]C# try/catch nightmare

I have a application with similar code (not written by me) 我有一个类似代码的应用程序(不是我写的)

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

} 

UPDATE - This is .NET C# & EnumerateSomeCoolHardwareDevice() is using SerialPort? 更新 - 这是.NET C#和EnumerateSomeCoolHardwareDevice()正在使用SerialPort?

I know how bad this code is but it works like this for a reason! 我知道这段代码有多糟糕,但它的作用是有原因的!

My question thou: I can see that it crashes somewhere in the EnumerateSomeCoolHardwareDevice(); 我的问题:我可以看到它在EnumerateSomeCoolHardwareDevice()中崩溃了; but it doesn't get caught by the Catch (...) - It just crashes with the send report dialog! 但它没有被Catch捕获(...) - 它只是与发送报告对话框崩溃了! This also currently only happen in the release build... Is their ANY reason why my exception will NOT be caught by the catch (...)? 这也只发生在发布版本中...他们的任何理由为什么我的异常不会被catch(...)捕获?

My guess is that you're not getting an Exception in your language/framework but rather EnumerateSomeCoolHardwareDevice() does weird things that simply cause the OS to kill your process. 我的猜测是你没有在你的语言/框架中得到异常,而是EnumerateSomeCoolHardwareDevice()做了一些奇怪的事情,只会导致操作系统终止你的进程。 Remember that hardware details are abstracted by frameworks like Java and .NET, so whenever you do something with hardware directly, you're probably relying on unmanaged resources ... and whatever goes wrong there can kill you, catch or not. 请记住,硬件细节是由Java和.NET等框架抽象出来的,所以每当你直接用硬件做事时,你可能都依赖于非托管资源......无论出现什么问题,都可以杀死你,抓住或不捕获。

One possible reason would be if the EnumerateSomeCoolHardwareDevice() function uses threading. 一个可能的原因是EnumerateSomeCoolHardwareDevice()函数使用线程。 If an exception is thrown in a thread and isn't handled within it's thread then it can crash an application. 如果在线程中抛出异常并且未在其线程内处理,那么它可能会使应用程序崩溃。 This simple app can demonstrate what I mean: 这个简单的应用程序可以证明我的意思:

    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);
        }
    }

If you run that the app will crash and burn rather than catching the exception as you might expect. 如果你运行该应用程序将崩溃和刻录,而不是像你期望的那样捕获异常。

In .NET catch (Exception ex) will only catch .NET exceptions, not native exceptions. 在.NET中, catch (Exception ex)只捕获.NET异常,而不是本机异常。

This question (catching native exceptions in C#) may help. 这个问题(在C#中捕获本机异常)可能会有所帮助。

Assuming .NET, if EnumerateSomeCoolHardwareDevice uses Win32 methods via PInvoke (to access the hardware) and an error occurs, most Native methods return an error code. 假设.NET,如果EnumerateSomeCoolHardwareDevice通过PInvoke使用Win32方法(访问硬件)并发生错误,大多数Native方法都会返回错误代码。 If that error code is not handled, and another native method is called anyway (perhaps with empty out parameters from the failed call), a serious native error (such as bad memory access or something similar) can cause a straight program crash, no exception thrown. 如果没有处理该错误代码,并且无论如何都要调用另一个本机方法(可能是来自失败调用的空出参数),严重的本机错误(例如错误的内存访问或类似的东西)可能导致程序直接崩溃,没有异常抛出。

Have you tried the attribute 你试过这个属性吗?

assembly:RuntimeCompatibility(WrapNonExceptionThrows = true) assembly:RuntimeCompatibility(WrapNonExceptionThrows = true)

That should wrap any non-.Net exceptions into System.Exception so it will be catched in your code. 这应该将任何非.Net异常包装到System.Exception中,以便它将被捕获到您的代码中。

If it is only happening on the production machine and not the dev machines then it could be down to DLL mismatches. 如果它只发生在生产机器而不是开发机器上,则可能是DLL不匹配。 Double check ALL the referenced DLLs and frameworks are the same version. 仔细检查所有引用的DLL和框架是否是相同的版本。

Secondly if the error is not being thrown by the EnumerateSomeCoolHardwareDevice() then it will crash the app as there is no way for the exception to get back up the stack (or thats my understanding of try/catches) in my experience this has happened to me before. 其次,如果EnumerateSomeCoolHardwareDevice()没有抛出错误,那么它将使应用程序崩溃,因为在我的经验中,没有办法让异常重新获得堆栈(或者这就是我对try / catches的理解)我之前。

Lastly, the microsoft error report usually allows you to inspect what will be sent to MS, this should let you see where the error happened and why (assuming it has readable information within it). 最后,微软错误报告通常允许您检查将发送给MS的内容,这应该让您看到错误发生的位置和原因(假设其中包含可读信息)。

Check the Event Viewer as the error should also be logged there, and normally provides an invaluable source of detail regarding the error and with a bit of digging through the error listed there you should be able to trace the fault. 检查事件查看器,因为错误也应该记录在那里,并且通常提供有关错误的宝贵详细信息来源,并且通过挖掘那里列出的错误,您应该能够跟踪故障。

If you are in .Net version 1.1 use a no parameters catch block like 如果您在.Net 1.1版中使用了无参数catch块之类的

catch{
...
}

Prior to .Net 2.0 there could be native exceptions that do not derive from System.Exception. 在.Net 2.0之前,可能存在未从System.Exception派生的本机异常。

Also hook to appdomain unhandled exception event and see what happens. 同时挂钩appdomain 未处理的异常事件,看看会发生什么。

There may be a try..catch inside EnumerateSomeCoolHardwareDevice() . EnumerateSomeCoolHardwareDevice()可能有一个try..catch。

If the exception is caught and handled there, the outer exception won't be hit unless the Exception is thrown again. 如果在那里捕获并处理异常,除非再次抛出异常,否则不会触发外部异常。

(Assuming Java) Both Error and Exception are subclasses of Throwable . (假设Java)Error和Exception都是Throwable的子类。 If there is an assertion failing in EnumerateSomeCoolHardwareDevice() for example you will get an Error. 例如,如果EnumerateSomeCoolHardwareDevice()的断言失败,您将收到错误。

My guess is that there's a stack overflow happening. 我的猜测是发生堆栈溢出。 The .NET VM simply shuts down Release build processes that encounter a stack overflow, no CLR exceptions thrown. .NET VM只关闭遇到堆栈溢出的Release构建过程,不会抛出CLR异常。 There's probably an internal try / catch inside that function that catches StackOverflowException one way or other, that's why it's not propagating to your code in Debug builds either. 在该函数中可能存在内部try / catch,它以某种方式捕获StackOverflowException,这就是为什么它不会传播到Debug构建中的代码。

The easiest way to figure out what's going on is by making a debug build, attaching a debugger and instructing the debugger to break before any exceptions are thrown (in Visual Studio, Debug/Exceptions and tick "Thrown" for "Common Language Runtime Exceptions" and possibly other ones as well, in cordbg.exe "catch exception") 找出正在发生的事情的最简单方法是进行调试构建,附加调试器并指示调试器抛出任何异常之前中断(在Visual Studio,Debug / Exceptions中为“Common Language Runtime Exceptions”勾选“Thrown”)可能还有其他一些,在cordbg.exe“catch exception”中)

If it is crashing madly and is using a SerialPort object then it is probably because at some point it skips onto a background thread and an exception happens here. 如果它疯狂地崩溃并且正在使用SerialPort对象,那么可能是因为它在某些时候会跳到后台线程并且在这里发生异常。 IIRC the .DataReceived event or however you get information back from a serial port returns data on a background thread. IIRC .DataReceived事件或者您从串行端口获取信息返回后台线程上的数据。 Should an exception be thrown in this routine then the entire application will bail. 如果在此例程中抛出异常,则整个应用程序将保释。

Find the background thread and put some exception handling round it. 找到后台线程并对它进行一些异常处理。

What types of exception have you seen behaving in this way? 您看到过哪种类型的例外行为? Do you have a list of them? 你有他们的清单吗?

Some exceptions will keep propgating up the call stack, even if they've been caught in a catch block, such as ThreadAbortException . 一些异常会继续调用调用堆栈,即使它们已经被catch块捕获,例如ThreadAbortException

Others are essentially unhandleable, such as StackOverflowException or ExecutionEngineException . 其他基本上是不可处理的,例如StackOverflowExceptionExecutionEngineException

If it is one of these (or some others I have probably missed), then the behaviour is probably as expected. 如果它是其中之一(或者我可能错过的其他一些),那么行为可能与预期的一样。 If it is some others, then a deeper look with more information will be necessary. 如果是其他人,则需要更深入了解更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM