Exception specifications: throw() useful?

This is a discussion on Exception specifications: throw() useful? within the C++ Programming forums, part of the General Programming Boards category; GotW #82: Debate #1 - Exception Safety and Specifications: Are They Worth It? Boost Library Requirements and Guidelines A non-inline ...

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    399

    Exception specifications: throw() useful?

    GotW #82: Debate #1 - Exception Safety and Specifications: Are They Worth It?
    Boost Library Requirements and Guidelines

    A non-inline function is the one place a "throws nothing" exception-specification may have some benefit with some compilers.
    The reasoning for not using exception specifications is pretty solid, but I think it is still a bit unclear whether or not throw() is useful. The STL uses throw() a lot, and I have some cleanup functions that mustn't throw. Should I use throw() for them or is it pointless and will only lead to extra compiler generated overhead? Should I bother using throw() for other functions that I can guarantee not to throw, but them throwing an exception is not really important either way?

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I wouldn't bother.
    If an exception is thrown when you have a throw() specification, std::terminate() is called and your program immediately dies.
    If an exception is thrown without the throw() specification and you don't catch it, the exception will bubble up to the top and your program will end.
    If you later decide that you do want to throw an exception, you would need to remove the throw() specification and make sure that everyone using your code is updated with the latest header files...
    If you're really worried about accidentally throwing an exception where it shouldn't be, just wrap a try {} catch (...) {} block around it; then you can at least log the error somewhere before either continuing or killing your program.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If an exception is thrown when you have a throw() specification, std::terminate() is called and your program immediately dies.
    If an exception is thrown without the throw() specification and you don't catch it, std::terminate() is called and your program immediately dies.
    Isn't it more like that?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by anon View Post
    Isn't it more like that?
    I don't know. I thought exceptions bubble up the call stack until they reach main() and if none of the calling functions catch it by then, std::terminate() is called.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I might be wrong, but if there is not a handler for an exception, then the standard allows stack unwinding not to happen.

    With neither VC++ nor GCC is the destructor called:

    Code:
    #include <iostream>
    
    struct X
    {
        ~X() { std::cout << "~X()\n"; }
    };
    
    X foo(bool b)
    {
        X x;
        if (!b) throw 666;
        return x;
    }
    
    int main()
    {
        //try {
            foo(false);
        //}
        //catch (int) {}
    }
    Implementation-wise, I suppose, it is known what exceptions are going to be handled for any piece of code.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,308
    Quote Originally Posted by cpjust View Post
    I wouldn't bother.
    If you're really worried about accidentally throwing an exception where it shouldn't be, just wrap a
    Code:
    try {} catch (...) {}
    block around it; then you can at least log the error somewhere before either continuing or killing your program.
    I wouldn't advise that!
    A try catch block self-documents that you expect the code inside to sometimes throw an exception. An empty catch block simply sweeps problems under the rug. Even with logging in there, can you be sure that the logging works since you will probably never actually test that code path? What if an exception was throwing inside a function in that try block that was actually caused by the logging module!

    For some reason I couldn't post without putting somew of that post into a CODE tag. How the heck was it posted originally!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,114
    Quote Originally Posted by iMalc
    I wouldn't advise that!
    A try catch block self-documents that you expect the code inside to sometimes throw an exception. An empty catch block simply sweeps problems under the rug. Even with logging in there, can you be sure that the logging works since you will probably never actually test that code path? What if an exception was throwing inside a function in that try block that was actually caused by the logging module!
    How would you handle the case where a destructor might otherwise throw an exception, and how would you handle the possibility of a logging module throwing an exception?

    I must say that at times I have used an empty catch block as a way out to suppress an exception from being thrown from a destructor. Thus far, I will admit that I have never properly considered what happens if an exception is thrown when I'm trying to log an exception.

    Incidentally, it should be possible to test that code path: simulate an exception, then check that an exception is not propagated and logging is correctly performed.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,308
    Quote Originally Posted by laserlight View Post
    How would you handle the case where a destructor might otherwise throw an exception, and how would you handle the possibility of a logging module throwing an exception?
    If I don't believe it's logically possible for the destructor to throw then I wont put a catch there. If it then does, it's fair enough for the program to crash and burn as something would have to have been pretty majorly wrong. If I believe it can throw, I would put the catch in there, but it so seldom comes up that I seriously can't remember having had to do it at all in recent years.
    I just don't like to program as though I'm paranoid until I've been given a good reason to be.

    I must say that at times I have used an empty catch block as a way out to suppress an exception from being thrown from a destructor. Thus far, I will admit that I have never properly considered what happens if an exception is thrown when I'm trying to log an exception.
    I've had to get to the bottom of exactly that kind of thing. A product I work on has an unhandled exception filter that can do one of various thing, one of which is to generate a stack trace. Unfortunately due to a bug, this sometimes itself crashed making it very hard to diagnose a customer's bug.
    The worst things though are empty catch(...) blocks. They stop the exception from reaching the unhandled exception filter and producing a stack trace or dump. The user keeps telling us that incorrect thing X happens, but we have to tell them that we can't diagnose that issue in the version they are using.

    Incidentally, it should be possible to test that code path: simulate an exception, then check that an exception is not propagated and logging is correctly performed.
    Yeah that was my thoughts too, and I've done this before, but I'm not sure many would bother.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lifetime of temporary during exception throw
    By brewbuck in forum C++ Programming
    Replies: 3
    Last Post: 05-22-2009, 05:08 PM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 03:39 PM
  3. Replies: 5
    Last Post: 06-07-2007, 12:10 AM
  4. std::bad_exception donīt throw exception
    By ripper079 in forum C++ Programming
    Replies: 2
    Last Post: 03-20-2003, 07:47 PM
  5. Exception specifications: good or bad?
    By Just in forum C++ Programming
    Replies: 0
    Last Post: 02-19-2003, 09:19 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21