5

Consider the following function defined in a C library:

void f(void (*callback)(int)) { callback(0); }

which will be called from a C++11 program defining callback(), possibly throwing an exception, as below:

void callback(int) { /* can I throw ? */}
try {
   f(callback);
} catch (...) {
   /* can the exception be caught ? */
}

My questions are:

  1. does the standard allows the callback to throw when called from f()? If not, must/should I declare callback() with the noexcept specifier?
  2. If yes, does the standard allows to catch the exception object being thrown?
Martin
  • 9,089
  • 11
  • 52
  • 87
  • Don't allow a C++ exception to cross over to C stack. The results of this are undefined. – n. m. could be an AI Aug 26 '14 at 09:51
  • 2
    To conform to the standard you have to declare `callback` as `extern "C"`. Most implementations will let you get away with omitting it, but strictly speaking the code should not even compile without it. Nothrow is not necessary, just don't throw. – n. m. could be an AI Aug 26 '14 at 10:06
  • 2
    http://stackoverflow.com/questions/9252139/passing-exceptions-across-a-c-api-boundary – Dean Aug 26 '14 at 10:56

1 Answers1

1

Below source code can be compliled.

exception.cpp:

extern "C"
void throwInCPP() {
    throw 5;
}

main.c

#include <stdio.h>
void throwInCPP();
void throwExp(void (*callback)()) {
    callback();
}

int main() {
    throwExp(throwInCPP);
    return 0;
}

When when it gets ran, exception will be thrown and the program unwind the stack try to find a catch block but it cannot. Then abort happens:

#0  0x00007ffff7238d67 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff723a118 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff7b2e1f5 in __gnu_cxx::__verbose_terminate_handler() ()
       from /usr/lib/libstdc++.so.6
#3  0x00007ffff7b2c076 in ?? () from /usr/lib/libstdc++.so.6
#4  0x00007ffff7b2c0c1 in std::terminate() () from /usr/lib/libstdc++.so.6
#5  0x00007ffff7b2c2d8 in __cxa_throw () from /usr/lib/libstdc++.so.6
#6  0x00000000004007fa in throwInCPP ()
#7  0x00000000004007bd in throwExp (callback=0x4007d4 <throwInCPP>) at main.c:6
#8  0x00000000004007cd in main () at main.c:11

I think you can always call a cpp function which throws an expection in c, but you can never put a catch block in c since it doesn't compile.

How is the C++ exception handling runtime implemented? This explains how does the exception work in c++.

I don't really think throw exception in c will be something good since you cannot do anything with it in the "normal" way.

Community
  • 1
  • 1
beeender
  • 3,555
  • 19
  • 32