Unable to catch c++ exception using catch (…)

2020-02-09 03:16发布

问题:

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?

回答1:

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

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



回答2:

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.



回答3:

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.



回答4:

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.