C++ – Access Violation issue with unhandled managed Exceptions in managed C++ .NET application


This is actually a solved problem, but it's so esoteric I thought I'd share it for other users.

Also perhaps others might suggest reasons?

Anyway, I'm working on a "mixed mode" .NET application written in managed C++, but with heavy links into existing native libraries.

The problem was, unhandled managed exceptions ended up as Win32 Access Violations. What I mean by this is that instead of showing the nice .NET dialog one gets with an unhandled managed exception, instead I would get the older style "Unhandled win32 exception occurred in…" message.

Here's the interesting thing: if I start the app in the debugger, then the thrown managed exception gets correctly picked up. i.e., the debugger shows me the line.

However, when executing normally, it would turn into this Access Violation. Attaching the debugger at that point would produce little useful information (it wouldn't even show a sensible stack trace).

So, to me it suggests that something is happening in native code just before the unhandled managed exception reaches the exception handler.

So anyway, I managed to solve the issue by comparing my project to a clean new C++ managed project generated by Visual Studio 2008.

The fix was to do the following:

  1. Change the /SUBSYSTEM flag (Project properties->Linker->System->SubSystem) from /SUBSYSTEM:WINDOWS to "Not Set"

  2. Switched from using old style WinMain() to using the new style main().

i.e. it used to be

  int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)

And it is now

int main(array<System::String ^> ^args)

[Why am I using this weird _tWinMain? This was what got generated by the Visual Studio .NET IDE many years ago when you create a sample mixed mode Windows app. It's always worked fine (until now) so I never bothered changing it. _tWinMain is just a macro to WinMain]

I made this change and the problem disappears. Unhandled .NET exceptions now get properly trapped so I can now actually debug them.

I also made the inverse change to the clean sample C++ app and proved that it was the cause.

So, really my questions is, what the heck is going on?

Was it just that I was using the old style WinMain instead of the new main(array <String^>^)?

Should I maybe report this to Microsoft (will anyone care 😉 )?

Best Solution

I am not really surprised.

If you write the top-level main in managed code, any managed exception that will bubble up, will be handled by managed code. The same as it would in C#. This is because the OS does not call directly into your int main(array<System::String ^> ^args) function. This is done by managed code which is either part of .net, or inserted at compile time. This is the code that notices and handles any escaping .net exceptions.

If you write your own native WinMain, there is no .net code calling into this function, so there is also no managed code able to handle the managed exceptions. When a managed exception is thrown, it appears to the OS as any other native windows exception.

Note that this is not an exact description of how main/WinMain is invoked. It's an educated guess based upon your problem description, and a little experience. I left out some details that I know about, and probably also detail which I am totally not aware of. But I am quite sure this is the essence of the story.