C ++ / CLI: selecting all (.NET / Win32 / CRT) exceptions

I know this is disapproving, but I have no options here. I am developing a C ++ / CLI application that has an error that I cannot track - mainly because it bypasses my current crash handler:

AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(&LogAndExit); Application::ThreadException += gcnew ThreadExceptionEventHandler(&LogAndExit); Application::SetUnhandledExceptionMode(UnhandledExceptionMode::CatchException); try { Application::Run(gcnew frmMain()); } catch (Exception^ ex) { LogAndExit(ex); } catch (...) { LogAndExit(); } 

Standard .NET failure handling, I suppose. MSDN reports that some of the CRT exceptions will hit the managed stack and silently cancel the application.

I read on _set_invalid_parameter_handler, but even if I get the LNK2001 error, it seems that it cannot be used with / clr: pure. Am I right or am I just pebkacing it and missing the lib file?

+6
source share
5 answers

Can you work in /clr mode? If you can try this:

 #include <exception> 

Then:

 try { try { Application::Run(gcnew frmMain()); } catch(const exception& ex) { throw gcnew System::Exception(gcnew System::String(ex.what())); } } catch (Exception^ ex) { LogAndExit(ex); } catch (...) { LogAndExit(); } 

One more thing worth noting: if your application is multi-threaded, you will only throw an exception from the thread in which frmMain() runs. Thus, making all of your entire application freeze impossible in this case!

+4
source

First of all, this does not work for forms.

In applications using Windows Forms, unhandled exceptions to the main application thread raise an Application.ThreadException event to be raised. If this event is processed, the default behavior is that the unhandled exception does not terminate the application, although the application remains an unknown state. In this case, the UnhandledException event did not raise. This behavior can be changed using the application configuration file or using the Application.SetUnhandledExceptionMode method of changing the mode to UnhandledExceptionMode.ThrowException before the ThreadException event the handler is connected. This applies only to the main theme of the application. UnhandledException event for unhandled exceptions, other topics.

Secondly, there may be an unmanaged exception (which is not of type System :: Exception ).

 try { Application::Run(gcnew frmMain()); } catch (Exception^ ex) { LogAndExit(ex); } catch (...) { LogAndExit(new Exception("Some Unmanage exception")); 

msdn - How to catch exceptions in Visual C ++

+1
source

There are several types of exception handling. What you posted will only handle managed exceptions.

It is also possible that C ++ code throws unmanaged exceptions (especially from the standard library). In addition, for unmanaged code, a Win32 exception can be thrown.

Get started here and familiarize yourself with handling structured exceptions (Win32 exceptions). C ++ and managed exceptions are SEH based, so if you handle SEH at the top of each thread in your process, you will be protected.

0
source

Not every crash is an exception, at least not right away. It is very possible that a wild pointer will stomp in .NET internal data structures so badly that when an exception is thrown, the managed handler cannot work correctly.

Try using your own handler instead. Visual C ++ provides __try / __except , but you need to make sure that the handler is on the call stack of each thread in your program, and it is still possible for the exception to go unhandled (for example, CreateThread with a pointer to an illegal instruction). To handle all extreme cases, you should use SetUnhandledExceptionFilter .

Note that with /clr:pure all code is CLR dependent and therefore prone to failure due to runtime corruption. Even native handlers can depend on the damaged state, although they are less fragile than MSIL-based handlers. For reliable error handling, you really need code that runs outside the process.

0
source

I recommend you try __try / __ except

 __try { Application::Run(gcnew frmMain()); } __except(EXCEPTION_EXECUTE_HANDLER) { LogAndExit(new Exception("Some Unmanage exception")); } 

MSDN documentation here:

http://msdn.microsoft.com/en-us/library/s58ftw19(v=vs.80).aspx

If you want to become very tricky, try double-packing as follows:

 __try { try { Application::Run(gcnew frmMain()); } catch(SEHException^ e) { LogAndExit(new Exception("Some Unmanage exception")); } catch(...) //Leave this out if you're /clr:pure { LogAndExit(new Exception("Some Unmanage exception")); } } __except(EXCEPTION_EXECUTE_HANDLER) { LogAndExit(new Exception("Some Unmanage exception")); } 

Structured exceptions are wrapped in SEHException ^ in general.

You also need to consider that you can actually catch an exception, but something in your LogAndExit method throws a secondary exception, which actually ends with your program. Try disabling the LogAndExit function and see if you can accidentally crash and not with a standard interrupt message and / or wrap your LogAndExit code in another try / catch that hides any exceptions.

As someone who has made significant contributions to C ++ / CLI, I can sympathize with your dilemma. We hope this solution helps.

Additional MSDN documentation on C ++ / CLI exception handling:

How to identify and install the global exception handler http://msdn.microsoft.com/en-us/library/171ezxzc.aspx

Exception handling in / clr http://msdn.microsoft.com/en-us/library/633chdda.aspx

0
source

Source: https://habr.com/ru/post/892346/


All Articles