0

I inherited a C++ project with a function defined like so:

void myDoc::parseDoc(string& path) throw(docError);

The parseDoc function calls a library that throws libError, and the main function that calls parseDoc catches both docError and libError and logs them. parseDoc doesn't throw any exceptions itself, but I would've expected the libErrors from the library to still get caught by main. They don't - I just get a core dump with nothing useful on the stack.

I tried various changes to parseDoc. Some of them get libError passed up the chain. and some don't:

  1. catch libError and rethrow it - doesn't work
  2. catch libError and copy it to a docError and throw that - works
  3. specify throw(docError, libError) and not catch anything - works
  4. remove the throw() from the function definition and not catch anything - works

So my question is - does adding a throw(docError) to this function definition specifically prevent other exceptions from being passed up the stack to the caller? If so, why would anyone want to do that? And if not specifying that a function throws exceptions just works the way I always thought exceptions were supposed to work, what's the point of the throw(e) specification in the first place?

Eli Sadoff
  • 7,173
  • 6
  • 33
  • 61
littlenoodles
  • 435
  • 4
  • 13
  • 1
    you may be interested in [this](http://stackoverflow.com/questions/9418180/function-exceptions-specification-and-standart-exceptions-foo-throwexceptio?rq=1) question. – jaggedSpire Jul 07 '16 at 20:24
  • I would say, *"start* by adding a "catch-all `try` statement" to the outer-level routine that will prevent the possibility of a core-dump. ### Then, "don't rely on being able to 're-throw' the exception that you presently have in your hand." Having caught a particular exception, and having decided that for whatever reason you can't handle it, throw a *new* one. – Mike Robinson Jul 07 '16 at 20:24
  • Actually, I just found http://www.gotw.ca/publications/mill22.htm, which explains this. I didn't realize that the throw specification is explicitly for the purpose of preventing throwing of other exception types. For hateful C++ theoretical reasons I don't begin to understand, but that the original coder thought he did... ;-) – littlenoodles Jul 07 '16 at 20:34
  • 2
    Do #4. Throw specifications are actually deprecated anyway. – kirbyfan64sos Jul 07 '16 at 20:35

1 Answers1

5

Yes, a throw specification does not allow any exceptions except the specified to escape the function.

As for why anyone would want that, the idea is documentation, showing exactly which exceptions the function will throw.

However, in reality, the concept proved to be so useless that throw specifications were (or will be, not sure about the exact status) actually removed in a newer version of C++. So the correct action to take is number 4, removing the specification.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • 1
    Are you sure that it was removed? As far as I know, it was only deprecated, cppreference.com says nothing about removal of this feature. – HolyBlackCat Jul 07 '16 at 20:37
  • 2
    There's a proposal here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0003r2.html Not sure about its final status. Might be in C++17. – Sebastian Redl Jul 07 '16 at 21:27
  • If they're taking suggestions, I'd suggest that when no catcher for an exception is found up the stack, and the default behavior is to core dump, please core dump without unwinding the stack first. Why on earth would it make sense, if you're going to core dump, to discard all of the local context for the dump - rendering it essentially useless. I guess that's implementation specific, but still... – littlenoodles Jul 09 '16 at 14:31
  • But the behavior isn't to core dump, it's to call the unexpected handler, which can be dynamically changed at runtime with `std::set_unexpected`. – Sebastian Redl Jul 10 '16 at 11:57