Uncatchable custom exception C++
Asked Answered
S

3

7

This has been driving me crazy all night.

class ExceptionImpl;

/**
* Custom Exception.
*/
class Exception : public virtual std::exception
{
  public:
    Exception( const Exception& original );

    Exception( const std::string& message );

    virtual ~Exception( void ) throw( );

    virtual const char* what( void ) const throw( );

  private:
    const std::unique_ptr< ExceptionImpl > m_pimpl;
};

I throw this custom exception from a library as follows

throw Exception( "Error message" );

and catch it in main via

try
{
   regex pattern(R"(a*)");

   Id::set_pattern_validator(pattern);

   assert(false);
}
catch( Exception const& exception )
{
   assert(true);
}

Id::set_pattern_validator is a static method within the Id class of the library and the source of the exception. I've tried everything i can to catch the exception but it fails to be caught.

catch( Exception )

catch( std::exception )

catch( ... )

Nada!

Terminal output is as follows.

"Terminate called after throwing an instance of 'Exception' what(): The pattern validator cannot be altered once set. Abort trap."

Now short of sacrificing a goat I'm at a loss on what to try next... any hints/tips???

Note: If i throw the custom exception within main i can catch it no problem.

Mac OS X environment using GCC with the C++0x support.

EDIT: A solution for now is to continue development on a linux based system (Fedora). I will not be accepting an answer as of yet. Thanks for everyones help.

Sub answered 25/6, 2011 at 12:38 Comment(10)
when you say "form a library", does it mean across DLL boundaries? in which case it's discouragedFolse
this is correct the Id class is defined in a shared object. If this is discouraged what are the alternatives (please don't say return codes).Sub
You really should avoid doing anything that is not necessary in the exception classes — and using PImpl and heap allocation strikes me as reaaally bad (ask yourself: what if constructing your exception throws std::bad_alloc). Also take a look at Boost.Exception.Kv
@Cat Plus Plus: Thanks for the tip i'll amend the code accordingly.Sub
@Cat: actually using pimpl for exceptions is recommended, otherwise you may get std::terminate when copying it. std::bad_alloc is definitely better. Edit: Boost.Exception uses pimpl.Realgar
Try to throw std::exception instead of yours and verify that this one is being caught.Fablan
@ybungalobill: Yeah, I've checked its implementation just now. Well, that's something new learned today. Thanks.Kv
I've tried to throw std::exception and std::runtime_error. No dice. It fails to be caught???Sub
@Cat Plus Plus: Just for completeness I applied your comments anyway and it had to effect. Since reverted.Sub
@BenCrowhurst: Have you tried stepping the code under debugger?Kv
L
7

If catch (...) (in an enclosing function in the same thread) doesn't handle it, your crash is not caused by a thrown an uncaught exception after all.

(Note: It's possible for an exception to be thrown and terminate the program even though it would have been caught. Throwing from a destructor or violating a throws clause are two ways for this to happen.)

Lovely answered 25/6, 2011 at 12:47 Comment(3)
Hmmm Terminal output is as follows. terminate called after throwing an instance of 'Exception' what(): The pattern validator cannot be altered once set. Abort trap. Ok i'll start looking at it from a different view.Sub
No, no threads are involved in this example. And your other suggests are not the cause.Sub
Better go looking for that goat.Articulate
B
1

If you throw the custom exception from inside main and can catch it, then you must be exhibiting UB somewhere in the call-stack which is resulting in the later exception not being caught.

Biffin answered 25/6, 2011 at 14:12 Comment(0)
A
0

I had similar problems.

I was using QT on Mac OSX 10.8 (Mountain Lion) using gcc47 (macports). Within a QT main, I called a method from a shared library which threw an exception defined in that shared library. No matter what kind of try-catch I placed around the method-call (catching the exception, catching a base, or even catch (…)), the termination handler was always called which resulted my program to abort. It was impossible to catch the exception.

First, I tried the -shared-libgcc option during linking. That was not the issue otherwise, the catch (…) clause would have worked.

Then I wrote a simple main without QT using hand-written makefiles, linked against the shared library. And that worked!

I concluded that the problem was caused by the difference in options that were passed to gcc (i.e. the difference between the makefile generated by QT/qmake and my hand-written one).

After some binary searching I found that the following option was causing my problems (while linking):

-mmacosx-version-min=10.5

After changing it to the following:

-mmacosx-version-min=10.6,

everything was working as expected.

I do not know why specifying the option to 10.6 solves the issue. Any thoughts on this?

Arndt answered 31/1, 2013 at 22:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.