catching unmanaged exceptions in managed code, not working in releasebuild

V

Vasco Lohrenscheit

Hi,

I have a Problem with unmanaged exception. In the debug build it works
fine to catch unmanaged c++ exceptions from other dlls with

//managed code:
try
{
//the form loads unmanaged dlls out of which unmanaged exception //get
thrown
Application::Run(new Form1());
} catch (std::exception& e)
{
//catching work in debud build, in release build a SEHException
//gets thrown
}
But with the release build the same c++ exceptions are not catched but I
get a SEHException from the .net framework. Any idea what can cause this
Problem? I already checked build options and c++ exceptions are enabled
in the release build too, so the problem has to lie somewhere else...

best regards,

Vasco Lohrenscheit
 
S

Steve McLellan

Vasco Lohrenscheit said:
Hi,

I have a Problem with unmanaged exception. In the debug build it works
fine to catch unmanaged c++ exceptions from other dlls with

//managed code:
try
{
//the form loads unmanaged dlls out of which unmanaged exception //get
thrown
Application::Run(new Form1());
} catch (std::exception& e)
{
//catching work in debud build, in release build a SEHException
//gets thrown
}
But with the release build the same c++ exceptions are not catched but I
get a SEHException from the .net framework. Any idea what can cause this
Problem? I already checked build options and c++ exceptions are enabled
in the release build too, so the problem has to lie somewhere else...

I'm more surprised you get the std exception at all - all our unmanaged
assertions get turned into SEHExceptions anyway. Try working out where the
exception's coming from in the first place, and any differences in the
compiler and linker settings between Debug and Release.

Steve
 
J

Julie

Steve said:
I'm more surprised you get the std exception at all - all our unmanaged
assertions get turned into SEHExceptions anyway. Try working out where the
exception's coming from in the first place, and any differences in the
compiler and linker settings between Debug and Release.

Steve

That is what I was going to respond as well, but didn't because I didn't have a
definitive answer.

Sounds like your debug build is behaving incorrectly, and release is operating
as it should.
 
V

Vasco Lohrenscheit

Julie said:
That is what I was going to respond as well, but didn't because I didn't have a
definitive answer.

Sounds like your debug build is behaving incorrectly, and release is operating
as it should.


Does anybody has a definitive answer here?

So unmanaged exception can't be catched in managed code? Well, thats
really bad. Will this change with the standardised c++/CLI binding? Are
there any possibilieties to extract the original unmanaged exception and
its type from the SEHException?

How do you handle unmanaged exceptions in managed code?


best regards,

Vasco Lohrenscheit
 
S

Steve McLellan

Vasco Lohrenscheit said:
Does anybody has a definitive answer here?

So unmanaged exception can't be catched in managed code? Well, thats
really bad. Will this change with the standardised c++/CLI binding? Are
there any possibilieties to extract the original unmanaged exception and
its type from the SEHException?

How do you handle unmanaged exceptions in managed code?

Have a look at SEHException - it allows you to retrieve info related to the
original exception (see MSDN for
System::Runtime::InteropServices::SEHException).

What's unusual is that you were able to catch the std::exception at all. I
don't know how this stands to change in the future; I'm writing production
code so haven't used any of the 2005 beta releases.

Also see this, and have a Google for information about exception handling in
mixed C++.
http://msdn.microsoft.com/library/d...cconBasicConceptsInUsingManagedExceptions.asp
 
V

Vasco Lohrenscheit

Steve said:
Have a look at SEHException - it allows you to retrieve info related to the
original exception (see MSDN for
System::Runtime::InteropServices::SEHException).

What's unusual is that you were able to catch the std::exception at all. I
don't know how this stands to change in the future; I'm writing production
code so haven't used any of the 2005 beta releases.

Also see this, and have a Google for information about exception handling in
mixed C++.
http://msdn.microsoft.com/library/d...cconBasicConceptsInUsingManagedExceptions.asp

mhh, if I understand the section "Catching Unmanaged C++ Types"
correctly, a catch(const std::exception& e) should work:

" * If an unmanaged C++ type is encountered, the exception is
unwrapped and compared to the type encountered. This comparison allows
an unmanaged C++ type to be caught in the normal way.
* However, if a catch clause of type SEHException or any of its
base classes is examined first, the clause will intercept the exception.
Therefore, you should place all catch clauses that catch unmanaged C++
types first before any catch clauses of managed types.
"

After some testing I've found several problems: The exceptions are only
catched if I debug with F5. Running without debugging neither in the
release nor in the debug build the exceptions are catched. I also tried
to catch the System::Runtime::InteropServices::SEHException and
System::Exception but they aren't catched neither.
But I have enabled the compiler option for exceptions (/EHsc) and
catching exceptions within the unmanaged code works fine.

Any ideas what can cause this strange behaviour? Could it be a problem
that the exceptions are thrown/catched across dll boundaries?

best regards,

Vasco Lohrenscheit
 
S

Steve McLellan

Steve said:
Have a look at SEHException - it allows you to retrieve info related to the
original exception (see MSDN for
System::Runtime::InteropServices::SEHException).
[snip]

mhh, if I understand the section "Catching Unmanaged C++ Types"
correctly, a catch(const std::exception& e) should work:

" * If an unmanaged C++ type is encountered, the exception is
unwrapped and compared to the type encountered. This comparison allows
an unmanaged C++ type to be caught in the normal way.
* However, if a catch clause of type SEHException or any of its
base classes is examined first, the clause will intercept the exception.
Therefore, you should place all catch clauses that catch unmanaged C++
types first before any catch clauses of managed types.
"

After some testing I've found several problems: The exceptions are only
catched if I debug with F5. Running without debugging neither in the
release nor in the debug build the exceptions are catched. I also tried
to catch the System::Runtime::InteropServices::SEHException and
System::Exception but they aren't catched neither.
But I have enabled the compiler option for exceptions (/EHsc) and
catching exceptions within the unmanaged code works fine.

Any ideas what can cause this strange behaviour? Could it be a problem
that the exceptions are thrown/catched across dll boundaries?

Hi,

Maybe. OK, with the following code, I catch an SEHException in both Debug
and Release modes, building into the same assembly. So it may be a DLL
boundary thing, which I can't easily test. It sounds like the debugger may
also be set to break on exceptions, which would give the appearance of
catching something. Try sticking a catch(...) and see if that catches it
(just as a test), otherwise I don't know what to suggest.

ManagedClass::SomeFunction()
{
try
{
// Throws an std::exception
UnmanagedClass::SomeStaticFunction();
}
catch ( System::Runtime::InteropServices::SEHException *ex )
{ }
catch ( std::exception *e )
{ }
catch (...)
{ }
}

UnmanagedClass::SomeStaticFunction()
{
throw std::exception( "test" );
}
 
R

Russell Hind

Vasco said:
//managed code:
try
{
//the form loads unmanaged dlls out of which unmanaged exception
//get thrown
Application::Run(new Form1());
} catch (std::exception& e)
{
//catching work in debud build, in release build a SEHException
//gets thrown
}
But with the release build the same c++ exceptions are not catched but I
get a SEHException from the .net framework. Any idea what can cause this
Problem? I already checked build options and c++ exceptions are enabled
in the release build too, so the problem has to lie somewhere else...

I've read the other replies and just wondered: Does Application::Run
have its own catch clause in? If so, I guess its a catch (SEHExecption)
so won't that mean and std::exception will get matched to the
SEHException clause in side Application::Run?

This is how Borland VCL works, each time a message is processed, it is
wrapped in a try/catch block that you can't over-ride.

(Difference is that there, c++ (unmanaged) exceptions aren't caught and
so do propergate back to the main function.

Cheers

Russell
 
S

Steve McLellan

Russell Hind said:
I've read the other replies and just wondered: Does Application::Run
have its own catch clause in? If so, I guess its a catch (SEHExecption)
so won't that mean and std::exception will get matched to the
SEHException clause in side Application::Run?

This is how Borland VCL works, each time a message is processed, it is
wrapped in a try/catch block that you can't over-ride.

(Difference is that there, c++ (unmanaged) exceptions aren't caught and
so do propergate back to the main function.

There may be something in this, except that if this were the case you'd be
getting an automatic 'unhandled exception' dialog popping up, and this
apparently isn't happening. Still ,in the absence of any more ideas it's
something to look at.

I was under the misguided impression that the exception handler was around
the DLL call. You could try looking at
System::AppDomain::CurrentDomain->UnhandledException and
Application::ThreadException. You can attach exception handlers there for
unhandled exceptions further up the stack.


Steve
 
V

Vasco Lohrenscheit

Ahh, thanks Russel. I guess that was the problem. If I catch the
exceptions directly after the call everything works fine.
There may be something in this, except that if this were the case you'd be
getting an automatic 'unhandled exception' dialog popping up, and this
apparently isn't happening. Still ,in the absence of any more ideas it's
something to look at.

Well, I got this unhandled exception dialog :)

btw: you don't need to catch the SEHException, but can catch the c++
exception directly.

I was under the misguided impression that the exception handler was around
the DLL call. You could try looking at
System::AppDomain::CurrentDomain->UnhandledException and
Application::ThreadException. You can attach exception handlers there for
unhandled exceptions further up the stack.

Isn't it possible to have a global try {} catch(const std::exception& e)
{} somewhere?
In the Application::ThreadException I guess you have to check the type
and then do the exception handling via if() else if()... ?


best regards,

Vasco Lohrenscheit
 
V

Vasco Lohrenscheit

Steve said:
I was under the misguided impression that the exception handler was around
the DLL call. You could try looking at
System::AppDomain::CurrentDomain->UnhandledException and
Application::ThreadException. You can attach exception handlers there for
unhandled exceptions further up the stack.

In Application::ThreadException I get a SEHException. Is it possible to
extract the original c++ exception from it?
Or any other way to handle c++ exceptions globaly in managed code?

best regards,

Vasco Lohrenscheit
 
R

Russell Hind

Vasco said:
In Application::ThreadException I get a SEHException. Is it possible to
extract the original c++ exception from it?
Or any other way to handle c++ exceptions globaly in managed code?

I doubt it. This is the problem with mixed language environments
(again, we have the same problem in C++Builder. Exceptions are normally
pascal. The Run() routine catches pascal exceptions but not C++
exceptions so you have to catch these everywhere yourself or just catch
it in the WinMain and exit the app.

If you could over-ride Application::Run (or a sub part of it) then maybe
it could set up the try catch for SEH then call a 'ProcessMessage'
method which you can over-ride and set up your own try catch for
std::exception and then call inherited ProcessMessage method.

But this would require a change to the CLR I guess.

Cheers

Russell
 
S

Steve McLellan

Russell Hind said:
I doubt it. This is the problem with mixed language environments
(again, we have the same problem in C++Builder. Exceptions are normally
pascal. The Run() routine catches pascal exceptions but not C++
exceptions so you have to catch these everywhere yourself or just catch
it in the WinMain and exit the app.

If you could over-ride Application::Run (or a sub part of it) then maybe
it could set up the try catch for SEH then call a 'ProcessMessage'
method which you can over-ride and set up your own try catch for
std::exception and then call inherited ProcessMessage method.

But this would require a change to the CLR I guess.

The whole unhandled exception system is a bit weird IMO - I don't know why
Application::ThreadException doesn't follow the same rules as the
UnhandledException handler for the domain. SEHExceptions allow you to
retrieve certain info out of them (have a look at the docs) but AFAIK, not
the underlying type. I'm hoping that MS will look at the way exceptions are
handled, and remove some of the stuff they've put in - it'd be nice if they
just let everything fly through. I guess the problem is that if you let
unmanaged exceptions fly about, some languages (like C#) wouldn't be able to
catch them at all. Exceptions are supposed to have an 'InnerException'
property, but I've not had a look at it. I don't see how it could enclose a
C++ exception though.

Anyway, if you find out any more, let me know, and good luck!

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top