views:

1921

answers:

4

I have a third-party library that is sometimes throwing an exception. So I decided to wrap my code in a try/catch(...) so that I could log information about the exception occurring (no specific details, just that it happened.)

But for some reason, the code still crashes. On client computers, it crashes hard and the code to log the exception in the catch(...) never gets executed. If I run this on my debug / development machine I get the popup asking me if I want to debug. When I do this, it reports 0xC0000005: Access violation reading location XXX.

The odd thing is that with an older version of the third-party library, the exact same code DOES catch the exception, and the code to log the exception DOES execute. (I verified this within VS watching the same conditions occur.)

Here's the pseudo-code that is executing:

pObject = pSystem->Get_pObject()
pSystem->DoSomethingThatMightDestroy_pObject();
try
{
 /*   Call to third party function that is throwing exception */
 pObject->SetValue(0);
}
catch (...)
{
 __DEBUG_LOG_POSITION__;  // A macro to log the current file line
 //  This code used to run in the older version of third-party library
 //  but the newer version just crashes before running the catch(...)
}

So I have two questions:

  1. Is there some change in the way the third party might have compiled the library so that my code wouldn't be able to catch the exception? (Yes, there is a chance I can get the third party to make whatever fixes are necessary and recompile for me, if I know what to tell them.)

  2. Assuming I can't get the third party to fix it, what can I do to catch these exceptions? I'm thinking along the lines of... is there some way for me to determine whether pObject was deallocated?

+3  A: 

AFAIK access violation don't throw exception... at least not standard ones!

Maybe catching windows-specific "native" exception would help : http://www.gamedev.net/reference/articles/article2488.asp

Klaim
Wow that is a REALLY useful article, and does actually contain a workable solution for me... the old library had to be built under VS2003, and the new library is meant for VS2008 - the critical difference. After setting my library to compile w/ option "Enable C++ Exceptions: Yes With SEH Exceptions (/EHa)" my code now catches this instance. For this reason I am awarding this response the correct answer.I want to say however that several of the other answers provide valid useful information, especially the one about "not much use in continuing..." so thanks to all!!
Michael Bray
It's generally a bad idea to catch SEH exceptions with C++ try/catch. There's a reason why MS disabled that by default in their newer compilers. Generally, you should use SEH constructs (like __try/__except) rather than enabling that compiler option.
jalf
Michael Bray> No problem, I guess there are a lot of answers here that help in this kind of problems. I'll vote for other ones too to make them up just under this answer.jalf> Indeed. That's what they do in the article.
Klaim
A: 

What you describe looks very much like ::terminate() is being called by the C++ runtime.

This is usually caused by a so-called double exception - somewhere an exception is thrown, stack unwinding begins and in one of the destructors invoked during stack unwinding also throws an exception. In this case ::terminate() is called and you can't really help the program.

If that's the case the only way around is to obtain a new version of the library where exceptions are not let outside of destructors. You can verify it quite easily - after the library has been loaded call ::set_terminate() and provide your own function and check if it is being called prior to your program crashing.

sharptooth
+1  A: 

If you are on the Windows platform you might try looking at __try

However, note that there is not much use in continuing execution unless you are really sure you can isolate and handle the exception.

Tim
+6  A: 

An access violation is not a C++ exception. It's a windows Structured Exception. You'll have to use _set_se_translator() if you want to catch them in catch(...).

You should probably google for all reasons catch(...) is evil and make sure you really want to do this.

Steve Fallows
This is a good bit of information... in my case, however, it appears that I have to use _set_se_translator() in the main() function (at least according to the example in the article referenced by sharptooth above)... one thing I didn't mention is that my code is actually a com object being loaded by another application (the third party application, in fact) and I have no control over the main() that is in use. Otherwise I think this would have been the best path.
Michael Bray
Ooops I meant reference in the article by Klaim. sorry!
Michael Bray