Throwing Exceptions from Constructors

When is it right for a constructor to throw an exception?

The constructor's job is to bring the object into a usable state. There are basically two schools of thought on this.

One group favors two-stage construction. The constructor merely brings the object into a sleeper state in which it refuses to do any work. There's an additional function that does the actual initialization.

I've never understood the reasoning behind this approach. I'm firmly in the group that supports one-stage construction, where the object is fully initialized and usable after construction.

One-stage constructors should throw if they fail to fully initialize the object. If the object cannot be initialized, it must not be allowed to exist, so the constructor must throw.

Throwing exceptions from constructors

Yes, throwing an exception from the failed constructor is the standard way of doing this. Read this FAQ about Handling a constructor that fails for more information. Having a init() method will also work, but everybody who creates the object of mutex has to remember that init() has to be called. I feel it goes against the RAII principle.

What happens if a constructor throws an exception?

No, throwing an exception is the best way to signal an error during object construction. (Since there's no return value, there's no other way, other than constructing a headless object, which is bad style in C++.)

From the man himself, Bjarne Stroustrup: http://www.stroustrup.com/bs_faq2.html#ctor-exceptions

(If you are working in a project where exceptions aren't allowed, then you have to make the constructor infallible, and move any logic that could fail into a factory function that has the possibility of returning an error.)

Re: "But my destructor was not called"

Indeed.
In C++ the lifetime of an object is said to begin when the constructor runs to completion. And it ends right when the destructor is called. If the ctor throws, then the dtor is not called.

(But dtors of any member variable objects, whose ctors already ran to completion before this ctor ran, are called.)

You should consult the standard, or a good textbook for more details, esp. related to what happens when inheritance is involved. As a general rule of thumb, destructors are called in the reverse order of construction.

Your question about why "~B" was not called in your specific code, it's because you do not catch the exception in main. If you change your code so that main catches the exception, then "~B()" will be called. But, when an exception is thrown which has no catch, the implementation is free to terminate the program without calling destructors or destroying statically initialized objects.

Reference in C++11 standard (emphasis mine):

15.5.1 The std::terminate() function [except.terminate]

1
In some situations exception handling must be abandoned for less subtle error handling techniques.

...

2
In such cases, std::terminate() is called (18.8.3). In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called.

As a side note, generally speaking with gcc and clang, ~B will be called anyways in your example program, while with MSVC, ~B will not be called. Exception handling is complex and the standard allows that compiler writers can experiment with and choose what implementation that they think is best in this regard, but they cannot choose to give undefined behavior.

If it's really important for your program that the destructors are called even in this case, then you should make sure to catch exceptions in main so that your code will be portable (work the same on all conforming compilers). For example:

int main() {
try {
A a;
} catch (...) {}
}

This way, compilers like MSVC will be obligated to call the destructor of B before exiting.

Can constructors throw exceptions in Java?

Yes, constructors can throw exceptions. Usually this means that the new object is immediately eligible for garbage collection (although it may not be collected for some time, of course). It's possible for the "half-constructed" object to stick around though, if it's made itself visible earlier in the constructor (e.g. by assigning a static field, or adding itself to a collection).

One thing to be careful of about throwing exceptions in the constructor: because the caller (usually) will have no way of using the new object, the constructor ought to be careful to avoid acquiring unmanaged resources (file handles etc) and then throwing an exception without releasing them. For example, if the constructor tries to open a FileInputStream and a FileOutputStream, and the first succeeds but the second fails, you should try to close the first stream. This becomes harder if it's a subclass constructor which throws the exception, of course... it all becomes a bit tricky. It's not a problem very often, but it's worth considering.

Exception handling within a constructor

Throwing an exception when appropriate is part of a constructor's job.

Let's consider why we have constructors at all.

One part is convenience in having a method that sets various properties, and perhaps does some more advanced initialisation work (e.g. a FileStream will actually access the relevant file). But then if it was really that convenient all the time we wouldn't sometimes find member initialisers convenient.

The main reason for constructors is so that we can maintain object invariants.

An object invariant is something we can say about an object at the beginning and end of every method call. (If it was designed for concurrent use we would even have invariants that held during method calls).

One of the invariants of the Uri class is that if IsAbsoluteUri is true, then Host will be string that is a valid host, (if IsAbsoluteUri is false Host might be a valid host if it's scheme-relative, or accessing it might cause an InvalidOperationException).

As such when I'm using an object of such a class and I've checked IsAbsoluteUri I know I can access Host without an exception. I also know that it will indeed be a hostname, rather than e.g. a short treatise on mediaeval and early-modern beliefs in the apotropaic qualities of bezoars.

Okay, so some code putting such a treatise in there isn't exactly likely, but code putting some sort of junk into an object certainly is.

Maintaining an invariant comes down to making sure that the combinations of values the object holds always make sense. That has to be done in any property-setter or method that mutates the object (or by making the object immutable, because you can never have an invalid change if you never have a change) and those that set values initially, which is to say in a constructor.

In a strongly typed language we get some of the checking from that type-safety (a number that must be between 0 and 15 will never be set to "Modern analysis has found that bezoars do indeed neutralise arsenic." because the compiler just won't let you do that.) but what about the rest?

Consider the constructors for List<T> that take arguments. One of them takes an integer, and sets the internal capacity accordingly, and the other an IEnumerable<T> that the list is filled with. The start of these two constructors are:

public List(int capacity)
{
if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", capacity, SR.ArgumentOutOfRange_NeedNonNegNum);

/* … */

public List(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");

So if you call new List<string>(-2) or new List<int>(null) you get an exception, rather than an invalid list.

An interesting thing to note about this case, is that this is a case where they could possibly have "fixed" things for the caller. In this case it would have been safe to consider negative numbers as the same as 0 and null enumerables as the same as an empty one. They decided to throw anyway. Why?

Well, we have three cases to consider when writing constructors (and indeed other methods).

  1. Caller gives us values we can use directly.

Eh, use them.


  1. Caller gives us values we can't meaningfully use at all. (e.g. setting a value from an enum to an undefined value).

Definitely throw an exception.


  1. Caller gives us values we can massage into useful values. (e.g. limiting a number of results to a negative number, which we could consider as the same as zero).

This is the trickier case. We need to consider:

  1. Is the meaning unambiguous? If there's more than one way to consider what it "really" means, then throw an exception.

  2. Is the caller likely to have arrived at this result in a reasonable manner? If the value is just plain stupid, then the caller presumably made a mistake in passing it to the constructor (or method) and you aren't doing them any favours in hiding their mistakes. For one thing, they're quite likely making other mistakes in other calls but this is the case where it becomes obvious.

If in doubt, throw an exception. For one thing if you're in doubt about what you should do then it's likely the caller would be in doubt about what they should expect you to do. For another it's much better to come back later and turn code that throws into code that doesn't than turn code that doesn't throw into code that does, because the latter will be more likely to turn working uses into broken applications.

So far I've only looked at code that can be considered validation; we were asked to do something silly and we refused. Another case is when we were asked to do something reasonable (or silly, but we couldn't detect that) and we weren't able to do it. Consider:

new FileStream(@"D:\logFile.log", FileMode.Open);

There's nothing invalid in this call that should definitely fail. All validation checks should pass. It will hopefully open the file at D:\logFile.log in read mode and give us a FileStream object through which we can access it.

But what if there's no D:\logFile.log? Or no D:\ (amounts to the same thing, but the internal code might fail in a different way) or we don't have permission to open it. Or it's locked by another process?

In all of these cases we're failing to do what is asked. It's no good our returning an object that represents attempts to read a file that are all going to fail! So again, we throw an exception here.

Okay. Now consider the case of StreamReader() that takes a path. It works a bit like (adjusting to cut out some indirection for the sake of example):

public StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
{
if (path==null || encoding==null)
throw new ArgumentNullException((path==null ? "path" : "encoding"));
if (path.Length==0)
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
Contract.EndContractBlock();

Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, true);
Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false);
}

Here we've got both cases where a throw might happen. First we've got validation against bogus arguments. After that we've a call to the FileStream constructor that in turn might throw an exception.

In this case the exception is just allowed to pass through.

Now the cases we need to consider are a tiny bit more complicated.

With most of the validation cases considered at the beginning of this answer, it didn't really matter in what order we did things. With a method or property we have to make sure that we've either changed things to be in a valid state or thrown an exception and left things alone, otherwise we can still end up with the object in an invalid state even if the exception was thrown (for the most part it suffices to do all of your validation before you change anything). With constructors it doesn't much matter what order things are done in, since we're not going to return an object in that case, so if we throw at all, we haven't put any junk into the application.

With the call to new FileStream() above though, there could be side-effects. It's important that it is only attempted after any other case that would throw an exception is done.

For the most part again, this is easy to do in practice. It's natural to put all of your validation checks first, and that's all you need to do 99% of the time. An important case though is if you are obtaining an unmanaged resource in the course of a constructor. If you throw an exception in such a constructor then it will mean the object wasn't constructed. As such it won't be finalised or disposed, and as such the unmanaged resource won't be released.

A few guidelines on avoiding this:

  1. Don't use unmanaged resources directly in the first place. If at all possible, work through managed classes that wrap them, so it's that object's problem.

  2. If you do have to use an unmanaged resource, don't do anything else.

If you need to have a class with both an unmanaged resource and other state, then combine the two guidelines above; create a wrapper class that only deals with the unmanaged resource and use that within your class.


  1. Better yet, use SafeHandle to hold the pointer to the unmanaged resource if at all possible. This deals with a lot of the work for point 2 very well.

Now. What about catching an exception?

We can certainly do so. The question is, what do we do when we've caught something? Remember that we have to either create an object that matches what we were asked for, or throw an exception. Most of the time if one of the things we've attempted in the course of that fails, there isn't anything we can do to successfully construct the object. We're likely therefore to just let the exception pass through, or to catch an exception just to throw a different one more suitable from the perspective of someone calling the constructor.

But certainly if we can meaningfully continue on after a catch then that's allowed.

So in all, the answer to "Can you use a throw or try and catch within a constructor?" is, "Yes".

There is one fly in the ointment. As seen above the great thing about throwing within a constructor is that any new either gets a valid object or else an exception is thrown; there's no in between, you either have that object or you don't.

A static constructor though, is a constructor for the class as a whole. If an instance constructor fails, you don't get an object but if a static constructor fails you don't get a class!

You're pretty much doomed in any future attempt to make use of that class, or any derived from it, for the rest of the life of the application (strictly speaking, for the rest of the life of the app domain). For the most part this means throwing an exception in a static class is a very bad idea. If it's possible that something attempted and failed might be attempted and succeed another time, then it shouldn't be done in a static constructor.

About the only time when you want to throw in a static constructor is when you want the application to totally fail. For example, it's useful to throw in a web application that lacks a vital configuration setting; sure, it's annoying to have every single request fail with the same error message, but that means you're sure to fix that problem!

Throwing an exception in a constructor of a c++ class

The destructor is not invoked because the object was never fully constructed. Calling it on a partially contructed object could be more dangerous, as it would try to undo things that were never done. It is up to you, as a programmer, to ensure that no memory (nor any other resource) leaks from the constructor in case of exceptions.

But, the destructors of base classes and member variables will be called! That's why it is preferable in most cases to rely on smart pointers or containers, that will handle resource management for you. Try to change you class like this:

#include <memory>

class Test{
public:
std::unique_ptr<Int[]> a;

Test(){
a=std::make_unique<Int[]>(10);
cout<<"inside Test constructor ..."<<endl;
throw(0);
}

~Test(){
//no need to delete[] a;
cout<<"inside Test destructor ..."<<endl;
}
};

It is a win-win situation. You will see that the destructors of Int will be called, and you have no need to manually handle memory.

Java Throwing exception in child constructor on super attribute

First, the super(); call has to be first. If you don't specify the call explicitly, it is done implicitly. That means the parent constructor will complete before your child constructor does anything else. After that, your child class may throw an exception based on anything done in the parent constructor. It sounds like you are making this harder than it is...

Throw exception in constructor c++

The short answer is, throwing stuff in the constructor is dangerous.

First, lets define the design problem: you have a class that can fail to initialize. If the class fails to initialize, it cannot be used (will cause additional errors if used), so the class failing is considered a "critical failure", atleast where the class is concerned.

In a nutshell, what we want to avoid is letting a user use a class that failed to initialize.

Imagine the following situation:

class A
{
public:
A()
{
stuff1 = malloc(100);//some dynamic memory allocation
throw "This throw is crazy";
stuff2 = malloc(100);//some dynamic memory allocation
}
~A() {free(stuff1); free(stuff2);}
private: void* stuff2;void* stuff2;
};

int main(int argc, char** argv)
{
A a;
}

Once you throw in the constructor, what happens to stuff? well, it is an instant memory leak. The destructor is never called. Which is baaaad. If you handle the exception:

int main(int argc, char** argv)
{
try
{
A a;
}
catch(...)
{
//can't do much here
}
}

You've lost the reference to A, which is a nightmare. So some people try to get away with this instead (Up front, it is still bad)

int main(int argc, char** argv)
{
A* a;

try { a= new A();}
catch(...){delete a;}
}

But that is just as bad. You may still have a reference to a (and the memory directly pointed to by a will not leak) but a is now in an unknown state...you'll still have to delete it some day, and the free for stuff2 failed.

One way to get around this is to make your constructor and destructor alot smarter. Catch any exceptions that can be thrown in the constructor, and clean up the object, returning a "zombie" object. And have the destructor easily be able to check for the zombie object. I find this method to be more complicated.

A better way to some is to use an initializer:

 class A
{
public:
A() {stuff1=null; stuff2=null;}
void init()
{
stuff1 = malloc(100);//some dynamic memory allocation
throw "This throw is crazy";
stuff2 = malloc(100);//some dynamic memory allocation
}
void destroy() {if (stuff1) {delete stuff1; stuff1=NULL;} if (stuff2) {delete stuff2; stuff2=NULL;}}
~A() {destroy();}
};

I don't like this because you still get "zombie" objects, and have all the added upkeep of calling init and destroy. Going back to the original problem, both a smarter constructor and providing initalizers still don't solve the nutshell statement: the end user can still (pretty easily, in fact) use an instance that is in an unknown state.

I like to follow a pseudo RAII (Resource Acquisition Is Initialization) here: what you want to to ensure that, if you have a reference to an object, it is a valid reference. Else, there should be no memory leaks. The best way (IMHO) to achieve this is to use a factory method, and keep all the initializes private.

 class A
{
public:
~A() {destroy();}
static A* MakeA()
{
A* ret = new A();
try { ret->init();}
catch(...)
{
delete ret;
return NULL;
}
return ret;
}
private: void* stuff1,*stuff2;
A() {stuff1=null; stuff2=null;}
void init()
{
stuff1 = malloc(100);//some dynamic memory allocation
throw "This throw is crazy";
stuff2 = malloc(100);//some dynamic memory allocation
}
void destroy() {if (stuff1) {delete stuff1; stuff1=NULL;} if (stuff2) {delete stuff2; stuff2=NULL;}}
};

Now the user can never make a valid reference to a failed object, which is nice.

Protips:

  1. Exception handling is slow. If you expect this to happen often, or don't think that it will be a fatal error, use error codes in your init statements. Error codes in the factory method can give the user more info as well.
  2. I used raw pointers in this answer cuz I'm too lazy to write all those characters in an answer. Always use smart pointers and this becomes even easier. Juggling raw pointers is only for the criminally insane. (CLARIFYING USE SMART POINTERS)

Edit: clarified what I'm lazy about



Related Topics



Leave a reply



Submit