We have an application which uses native libraries, and is written in C++/CLI.
Our native libraries have their own C++ exception class, ErrorException.
The code is structured in such a way that the main loop of the application is in native code, which then calls into the (managed) application code, which then in turn sometimes calls back into the native library.
The native libraries are compiled with /EHsc (except for one which is compiled with /EHa, which seems wrong to me, due to the problem that catch(...) catches structured exceptions such as access violations!).
What I've done is that I've wrapped (most) functions in the C++/CLI code which (i believe) can throw managed exceptions in MANAGED_TRY_START
/MANAGED_TRY_END
macros as defined below:
#define MANAGED_TRY_START try {
#define MANAGED_TRY_END \
} \
catch(System::Runtime::InteropServices::SEHException^) { \
throw; \
} \
catch(System::Exception^ ex) { \
ConvertAndThrowSystemException(ex); \
throw NULL; \
} \
with ConvertAndThrowSystemException
being a function which turns a System::Exception into an ErrorException and throws that.
Now, my question is, is that enough? I ask because this particular application is displaying frequent instability and memory issues, and I fear that exceptions are at fault.
On a related note, we use dr.memory as our Valgrind replacement on windows for native code, but it doesn't seem to like .Net. Does anyone have a recommendation for a similar tool which does? We've tried Deleaker, and we get pretty strange results from it, like it claiming that stack allocated objects are being leaked.
Specifically, let's say the stack looks like: foo() [native] bar() [managed] foobar() [native] ...
and foo() throws a C++ exception. foobar()'s call to foo is within a try block with a corresponding catch() block for the type thrown by foo(). foobar() was compiled with /Ehsc.
Which of the following cases have foobar() catch the exception, with all intervening C++ stack objects being properly destroyed, if either does?
- bar() has no try/catch
- bar()'s contents is wrapped in my
MANAGED_TRY_START
/MANAGED_TRY_END
macros