CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Exception specifications and Visual Studio 2008

    I don't tend to use exception specifications, but not for the reason that will become apparent as you read this post...

    I'm writing I presentation on exception safety, and wanted to write a short bit on exception specifications. So to give an example of behaviour, I wrote the following bit of code with the intention of expanding it in the next slide or so:

    Code:
    #include <iostream>
    #include <stdexcept>
    
    void f() throw()
    {
      throw std::runtime_error("blah");
    }
    
    int main()
    {
      try
      {
        f();
      }
      catch(const std::exception& e)
      {
        std::cerr << e.what() << std::endl;
      }
    }
    Since I figure someone might ask for the slides and try to run the examples, I thought I should check my examples compile and run. The interesting thing is, with this example Visual Studio 2008 doesn't do what I'd expect. Before I say anymore I'd like to point out that the 2003 C++ Standard states the following:

    Whenever an exception is thrown and the search for a handler (15.3) encounters the outermost block of a function with an exception-specification, the function std::unexpected() is called (15.5.2) if the exception-specification does not allow the exception. [ Example:
    Code:
    class X { };
    class Y { };
    class Z: public X { };
    class W { };
    
    void f() throw (X , Y)
    {
      int n = 0;
      if (n) throw X (); / / OK
      if (n) throw Z (); / / also OK 
      throw W (); / / will call std::unexpected()
    }


    The function std::unexpected() may throw an exception that will satisfy the exception-specification for which it was invoked, and in this case the search for another handler will continue at the call of the function with this exception specification (see 15.5.2), or it may call std::terminate().
    In addition the 2011 C++ Standard states:

    Whenever an exception is thrown and the search for a handler (15.3) encounters the outermost block of a function with an exception-specification that does not allow the exception, then,
    — if the exception-specification is a dynamic-exception-specification, the function std::unexpected() is called (15.5.2),
    — otherwise, the function std::terminate() is called (15.5.1).
    [ Example:
    Code:
      class X { };
      class Y { };
      class Z: public X { };
      class W { };
    
      void f() throw (X, Y) {
        int n = 0;
        if (n) throw X(); // OK
        if (n) throw Z(); // also OK
        throw W(); // will call std::unexpected()
      }
    —end example ]

    [ Note: A function can have multiple declarations with different non-throwing exception-specifications; for this purpose, the one on the function definition is used. —end note ]

    10 The function unexpected() may throw an exception that will satisfy the exception-specification for which it was invoked, and in this case the search for another handler will continue at the call of the function with this exception-specification (see 15.5.2), or it may call std::terminate().
    With respect to behaviour, I have the following points:

    1) If I compile the example code as is, here is what I'd expect. The exception thrown in f() will not allowed to be propagated, instead, the default unexpected_handler will be called which in-turn will call std::terminate().

    GCC does as expected, however, Visual Studio 2008 does something very different...

    In release mode (running within the IDE) at run-time the debugger throws up an unhandled exception message box, if I say continue, it seemingly gets stuck in an infinite loop of breakpoint triggers and throwing up unhandled exception boxes around the same code section. The default unexpected_handler doesn't appear to ever be called. If run outside of the IDE a the console states:

    "This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information."

    and a just-in-time debugger window gets thrown up.

    In debug mode (both when run inside the IDE and outside the IDE), it is almost as if the throw() specifier doesn't exist, the exception is propagated and caught in the catch statement. The default unexpected_handler does not get called and the program exits uneventfully with code 0.

    2) If I modify the example as follows adding in the user defined function unexpected_exception_handler and calling set_unexpected:

    Code:
    #include <iostream>
    #include <stdexcept>
    
    void f() throw()
    {
      throw std::runtime_error("blah");
    }
    
    void unexpected_exception_handler() 
    {  
      std::cout << "unexpected_exception_handler: Unexpected exception caught" << std::endl;
      std::terminate();
    }
    
    int main()
    {
      std::set_unexpected( &unexpected_exception_handler );
    
      try
      {
        f();
      }
      catch(const std::exception& e)
      {
        std::cerr << e.what() << std::endl;
      }
    }
    I would expect that the user defined unexpected_exception_handler function will be called, which will in-turn call terminate. Again, GCC behaves as expected. But Visual Studio 2008 doesn't, at least not quite.

    In release mode, if run outside of the IDE, the VS compilation behaves the same as the previous release compilation (when outside the IDE with the just in time debugger window being thrown up). The user defined unexpected_exception_handler doesn't get called.

    If run inside the IDE, then continuing past an unhandled exception box and a host of breakpoint triggers, the compilation does call the user defined unexpected_exception_handler and the calls terminate, exiting gracefully with code 3.

    In debug mode (both when run inside the IDE and outside the IDE), the VS compilation behaves the same as the previous debug compilation, propagating the exception that is then caught in the catch statement and then it exits uneventfully (but incorrectly) with code 0.

    3) If I move the call to set_unexpected to within the try block as follows:

    Code:
    #include <iostream>
    #include <stdexcept>
    
    void f() throw()
    {
      throw std::runtime_error("blah");
    }
    
    void unexpected_exception_handler() 
    {  
      std::cout << "unexpected_exception_handler: Unexpected exception caught" << std::endl;
      std::terminate();
    }
    
    int main()
    {
      try
      {
        std::set_unexpected( &unexpected_exception_handler );
        f();
      }
      catch(const std::exception& e)
      {
        std::cerr << e.what() << std::endl;
      }
    }
    then GCC still behaves as expected, but Visual Studio does something different again.

    In both release and debug modes (both when run inside and outside the IDE), it behaves as if the throw() specifier does not exist, propagating the exception to the catch block and then exiting with code 0. In all cases for this third version of the example, the user defined unexpected_exception_handler is not called.

    If any of you have a later version of Visual Studio (I'm using 2008 Professional 9.0.21022.8), can you see if you get the same behaviour? Either way, unless you can see that I have done something really stupid, I'm thinking of raising a compiler bug.

    So much for writing a bit of demo code to demonstrate exception specifications!

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Exception specifications and Visual Studio 2008

    Quote Originally Posted by PredicateNormative View Post
    I don't tend to use exception specifications, but not for the reason that will become apparent as you read this post...
    Exception specifications -- see what Herb Sutter has to say about the whole thing:

    http://www.gotw.ca/publications/mill22.htm

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Exception specifications and Visual Studio 2008

    Quote Originally Posted by Paul McKenzie View Post
    Exception specifications -- see what Herb Sutter has to say about the whole thing:

    http://www.gotw.ca/publications/mill22.htm

    Regards,

    Paul McKenzie
    That's a great page. A few years ago when I was having issues with exception specifications not doing what I'd expected, I came across that same article, and by the time I'd finished reading it, I had decidedly jumped onto the "don't do it" team. However, even so, I still wanted in the presentation to cover how they actually work, which is why I put the example together. The fact that Visual Studio is clearly not working as it should lends extra ammunition to the argument to not bother using them, though for a different reason to why I stopped using them (covered by the article to which you have provided a link).

  4. #4
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Exception specifications and Visual Studio 2008

    As of c++11, they were outright deprecated.

    They have been replaced by a compile time "noexcept" spefication.

    EDIT: To answer your question, I see nothing stupid in your example. I'll try out the code at work on VS2008 & VS2010. On Monday.

    Quite frankly, the fact that your example is correct, but fails to do what is expected makes it the BEST snippet you could possibly hand out
    Last edited by monarch_dodra; March 24th, 2012 at 11:58 AM.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  5. #5
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Exception specifications and Visual Studio 2008

    Quote Originally Posted by monarch_dodra View Post
    As of c++11, they were outright deprecated.

    They have been replaced by a compile time "noexcept" spefication.

    EDIT: To answer your question, I see nothing stupid in your example. I'll try out the code at work on VS2008 & VS2010. On Monday.

    Quite frankly, the fact that your example is correct, but fails to do what is expected makes it the BEST snippet you could possibly hand out
    Sorry about my delay in replying, I've been having trouble logging in. It seems like someone has been doing some site "improvements".

    Anyway, the addition of a compile time noexcept specification is very welcome.

    I guess you are probably right. I'll include the example in my slides anyway.

    Did you manage to try it on VS2010, I'd be interested to see if it does the right thing.

  6. #6
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Exception specifications and Visual Studio 2008

    Just tested with 2005;2008;2010: "blah". I did some research, to try and find if there was some sort of switch to make it work and found this. I think it is relevant to your interests. Long story short: VS don't do exception specifications.

    These lines in particular:
    Quote Originally Posted by MSDN
    Visual C++ departs from the ANSI Standard in its implementation of exception specifications. The following table summarizes the Visual C++ implementation of exception specifications:
    Quote Originally Posted by MSDN
    throw(): The function does not throw an exception. However, if an exception is thrown out of a function marked throw(), the Visual C++ compiler will not call unexpected (see unexpected (CRT) and unexpected (<exception>) for more information). If a function is marked with throw(), the Visual C++ compiler will assume that the function does not throw C++ exceptions and generate code accordingly. Due to code optimizations that might be performed by the C++ compiler (based on the assumption that the function does not throw any C++ exceptions) if a function does throw an exception, the program may not execute correctly.
    Yeah, so Microsoft went with a pure optimization scheme, but with no safety net. Not that it isn't a smarter approach, but I always hate it when things deviate from the standard with no prior warning.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  7. #7
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Exception specifications and Visual Studio 2008

    Quote Originally Posted by monarch_dodra View Post
    Just tested with 2005;2008;2010: "blah". I did some research, to try and find if there was some sort of switch to make it work and found this. I think it is relevant to your interests. Long story short: VS don't do exception specifications.

    These lines in particular:




    Yeah, so Microsoft went with a pure optimization scheme, but with no safety net. Not that it isn't a smarter approach, but I always hate it when things deviate from the standard with no prior warning.
    That is a really helpful bit of research, thank you very much. I wonder why Microsoft don't state that they are non-compliant in a compiler warning or something.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured