G
Guest
I'm left a little confused about the correct way to handle exceptions thrown
from unmanaged code.
Specifically, I've got a legacy MFC based DLL that's wrapped by C++/clr
exposing it to a fairly straight forward C# console app (VisualStudio 2005 if
that matters).
According to a fairly brief comment in the documentation for SEHException:
"the SEHException class does not cause unmanaged C++ exception destructors be
called. To ensure that unmanaged C++ exception destructors are called, use
the following syntax in the catch block."[1]
The example C++ code shows a catch(...){} clause being used.
What I've found is that the recommended construct has *no effect* on the
execution of unmanaged C++ exception destructors. They will infact be called
as the exception goes out of scope just like it's supposed to.
With one exception...
The auto delete functionality of MFC based CException is not provided for.
In my mind, this really has nothing to do with managed vs unmanaged code
since plain old C++ exceptions won't provide for CException auto deletion
unless you use the godaweful TRY, CATCH, and CATCH_ALL macros or call the
exceptions Delete() member explicitly. This is just how you're supposed to
use MFC exceptions.
BTW, according to the Exception Handling in MFC documentation: "If you're
writing a new application using MFC, you should use the C++ mechanism. You
can use the macro-based mechanism if your existing application already uses
that mechanism extensively."[2]
I have verified that the default CException to SEHException conversion
mechanism does *not* call the exception's Delete() member. I think this is a
bug in the CLR, but I'm not sure where to post it. Any thoughts or comments?
It sounds like the only correct way to handle calling from managed to
unmanaged code is:
1) Guarantee the invoked unmanaged code will *never* generate an MFC
exception. Or,
2) Wrap every call into unmanaged MFC code with the following:
try
{
// Call unmanaged code
}
catch (CException* e)
{
// Pull any info you need from the exception.
e->Delete();
throw UserDefinedOrSEHException();
}
What am I missing since that looks pretty darn gross?
[1]
http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.sehexception.aspx
[2] http://msdn2.microsoft.com/en-us/library/t078xe4f.aspx
from unmanaged code.
Specifically, I've got a legacy MFC based DLL that's wrapped by C++/clr
exposing it to a fairly straight forward C# console app (VisualStudio 2005 if
that matters).
According to a fairly brief comment in the documentation for SEHException:
"the SEHException class does not cause unmanaged C++ exception destructors be
called. To ensure that unmanaged C++ exception destructors are called, use
the following syntax in the catch block."[1]
The example C++ code shows a catch(...){} clause being used.
What I've found is that the recommended construct has *no effect* on the
execution of unmanaged C++ exception destructors. They will infact be called
as the exception goes out of scope just like it's supposed to.
With one exception...
The auto delete functionality of MFC based CException is not provided for.
In my mind, this really has nothing to do with managed vs unmanaged code
since plain old C++ exceptions won't provide for CException auto deletion
unless you use the godaweful TRY, CATCH, and CATCH_ALL macros or call the
exceptions Delete() member explicitly. This is just how you're supposed to
use MFC exceptions.
BTW, according to the Exception Handling in MFC documentation: "If you're
writing a new application using MFC, you should use the C++ mechanism. You
can use the macro-based mechanism if your existing application already uses
that mechanism extensively."[2]
I have verified that the default CException to SEHException conversion
mechanism does *not* call the exception's Delete() member. I think this is a
bug in the CLR, but I'm not sure where to post it. Any thoughts or comments?
It sounds like the only correct way to handle calling from managed to
unmanaged code is:
1) Guarantee the invoked unmanaged code will *never* generate an MFC
exception. Or,
2) Wrap every call into unmanaged MFC code with the following:
try
{
// Call unmanaged code
}
catch (CException* e)
{
// Pull any info you need from the exception.
e->Delete();
throw UserDefinedOrSEHException();
}
What am I missing since that looks pretty darn gross?
[1]
http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.sehexception.aspx
[2] http://msdn2.microsoft.com/en-us/library/t078xe4f.aspx