Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my C++ exceptions not being caught?

I have some C++ code that uses a very standard exception pattern:

try {
  // some code that throws a std::exception
}
catch (std::exception &e) {
  // handle the exception
}

The problem is that the exceptions are not being caught and I cannot figure out why.

The code compiles to a static library in OS X (via Xcode). The library is linked into a Cocoa application, with a call to the function in question happening via an Objective-C++ thunk. I suspect that the interplay between Objective-C and C++ is the culprit but all my attempts to pin this down have failed.

I have not been able to create a simple example that reproduces this behavior in a simple example. When I take the relevant code out of the context of my big program everything works.

Can anyone suggest why my exceptions are not being caught?

like image 302
gauss256 Avatar asked Sep 04 '09 06:09

gauss256


5 Answers

One little known gotcha with exceptions relates to the access of the base class.

If you are actually throwing a class that derives privately from std::exception then the std::exception handler will not be chosen.

For example:

#include <iostream>

class A { };
class B : private A { } ;

int main ()
{
  try
  {
    throw B ();
  }
  catch (A & )
  {
    std::cout << "Caught an 'A'" << std::endl;
  }
  catch (B & )
  {
    std::cout << "Caught an 'B'" << std::endl;
  }
}

Usually, such an order of handlers would result in the 'B' handler never being selected, but in this case 'B' dervies from 'A' privately and so the catch handler for type 'A' is not considered.

like image 184
Richard Corden Avatar answered Oct 02 '22 13:10

Richard Corden


I can offer two theories:

  1. the exception gets caught before it comes your catch clause; any function on the stack might be the culprit. As Michael proposes, try catching everything.
  2. exception unwinding fails to locate your handler. To analyze this in more detail, you would have to step through the exception unwinding code, which is very hairy. See whether compiling the Objective-C code with -fobjc-exceptions helps.
like image 26
Martin v. Löwis Avatar answered Oct 02 '22 13:10

Martin v. Löwis


C++ allows you a variety of options for catching: value, reference or pointer. Note that this code only catches std::exceptions passed by reference or value:

try {
  // some code that throws a std::exception
}
catch (std::exception &e) {
  // handle the exception
}

It's likely that the exception is being passed by pointer:

catch (std::exception* e)

Check the code that is throwing the exception, and see how it's doing it.

As Mark points out, if you catch by value instead of by reference you risk slicing your object.

like image 18
Bill Avatar answered Oct 18 '22 20:10

Bill


Try a catch(...) {} block, see if an exception is really thrown.

like image 16
Michael Foukarakis Avatar answered Oct 18 '22 22:10

Michael Foukarakis


I suspect that the interplay between Objective-C and C++ is the culprit but all my attempts to pin this down have failed.

You're probably right, although it's hard to track down.

First, GCC explicitly does not allow you to throw exceptions in Objective C++ and catch them in C++ ("when used from Objective-C++, the Objective-C exception model does not interoperate with C++ exceptions at this time. This means you cannot @throw an exception from Objective-C and catch it in C++, or vice versa (i.e., throw ... @catch).")

However, I think you're describing a case where Objective C++ calls C++ code, the C++ code throws and you're hoping for C++ code to catch the exception. Unfortunately I'm having difficulty finding documentation for this specific case. There is some hope because, "It is believed to be safe to throw a C++ exception from one file through another file compiled for the Java exception model, or vice versa, but there may be bugs in this area." If they can do it for Java, there is a chance they can do it for Objective C++.

At the very least, you'll need to specify -fexceptions at compile time ("you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++"). Again, that doesn't specifically mention Objective C++ but it may apply.

like image 7
Max Lybbert Avatar answered Oct 18 '22 21:10

Max Lybbert