48

I am not sure if this is a issue with the compiler or if I am doing something wrong. I am using Visual Studio 2013 compiler.

I have a class where I need to acquire significant amount of resources in my constructor initializer list most of which can throw an exception. I wrapped up the member initializer list in a function try block and caught the exception there. But my program still aborts even though the catch clause doesn't re-throw the exception. I am not allowed to post the actual code. So I have reproduced the issue with this equivalent demo code. Can someone please help me address this?

#include <iostream>
using namespace std;
class A{
public:
    A() try : i{ 0 }{ throw 5; }
    catch (...){ cout << "Exception" << endl; }
private:
    int i;
};


int main(){
    A obj;
}

On executing this code I get a windows alert "abort() has been called". So I guess the system is treating this as an uncaught exception and calling terminate().

On the other hand if I wrap the construction of the object in main() in a try-catch block then the exception is caught properly and the program terminates normally.

Can someone please tell me if I am doing something wrong here?

MS Srikkanth
  • 3,829
  • 3
  • 19
  • 33
  • 4
    look at http://www.gotw.ca/gotw/066.htm for an discussion about this problem – Jan Herrmann Jan 13 '15 at 11:45
  • Thank you so much Jan Herrmann. It obviously makes a lot of sense for the standard to say that if an exception is not rethrown or if a new esception is not thrown from the function try block of the constructor then it will be automatically rethrown at the end of the catch block. This makes perfect sense now. Perhaps as suggested pimpl idiom is what I should start using. Thanks a lot again – MS Srikkanth Jan 13 '15 at 11:51
  • 20
    Extra points for *“I am not allowed to post the actual code. So I have reproduced the issue with this equivalent demo code.”* You've made a very good [MCVE](https://stackoverflow.com/help/mcve). – 5gon12eder Jan 13 '15 at 11:53
  • 1
    Excellently formed question. – Lightness Races in Orbit Jan 13 '15 at 11:58
  • 12
    If all questions were written like this, the market for crystal balls would plummet. – molbdnilo Jan 13 '15 at 12:42

4 Answers4

31

There's a relevant gotw

http://gotw.ca/gotw/066.htm

Basically even if you don't throw in your catch block, the exception will automatically be rethrown

If the handler body contained the statement "throw;" then the catch block would obviously rethrow whatever exception A::A() or B::B() had emitted. What's less obvious, but clearly stated in the standard, is that if the catch block does not throw (either rethrow the original exception, or throw something new), and control reaches the end of the catch block of a constructor or destructor, then the original exception is automatically rethrown.

dau_sama
  • 4,247
  • 2
  • 23
  • 30
  • That page is a really excellent read. Didn't know the function-try-block syntax existed before this question; learned a lot from that link! In particular, there's the fantastic analogy: "If construction of any base or member object fails, the whole object *must* fail ... no way for a human to [be born] if any of it's vital organs were never formed". – OJFord Jan 13 '15 at 18:32
  • the whole gotw website is a gold mine for any C++ developer! Along with Bjarne's website, parashift, cppreference and cplusplus – dau_sama Jan 13 '15 at 19:20
  • I've been discovering just that in the 48mins since my above comment! A shame most recent was 1/1/08. – OJFord Jan 13 '15 at 19:22
22

This is normal behaviour according to the cppreference.com documentation for function-try blocks: a so-called function-try-block on a constructor or destructor must throw from its catch-clause or else there is an implicit rethrow after the catch-clause.

This makes perfect sense: the object A has not been properly constructed and hence is not in a state fit for use: it must throw an exception. You have to ensure whether the construction succeeded at the place where the object is constructed, i.e. in the case of your example in main().

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Walter
  • 44,150
  • 20
  • 113
  • 196
  • 4
    Upvoting because this answer has a more human-readable answer than the quoted standardese. To the OP: your problem is that one or more of your members are in an unconstructed state (since you don't know which member's construction threw, you don't know which members have been fully constructed). Thus your class is not fully constructed. Having it rethrow ensures that you cannot use this instance. Members which did get fully constructed will be appropriately destructed. – Andre Kostur Jan 13 '15 at 15:41
9

Exception cannot be caught in constructor function-try-block.

n3376 15.2/15

The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.

You should catch it in object creation place.

Walter
  • 44,150
  • 20
  • 113
  • 196
ForEveR
  • 55,233
  • 2
  • 119
  • 133
0

I suggest you read the article: "GotW #66 Constructor Failures"on the site:http://gotw.ca/gotw/066.htm