How to Handle Failure in Constructor in C++

What is the best way to communicate that your constructor has failed in C#?

throw new ArgumentException("Reason", "param name");

What's the best technique for exiting from a constructor on an error condition in C++

The best suggestion is probably what parashift says. But read my caution note below as well please.

See parashift FAQ 17.2

[17.2] How can I handle a constructor
that fails?

Throw an exception.

Constructors don't have a return type,
so it's not possible to use return
codes. The best way to signal
constructor failure is therefore to
throw an exception. If you don't have
the option of using exceptions, the
"least bad" work-around is to put the
object into a "zombie" state by
setting an internal status bit so the
object acts sort of like it's dead
even though it is technically still
alive.

The idea of a "zombie" object has a
lot of down-side. You need to add a
query ("inspector") member function to
check this "zombie" bit so users of
your class can find out if their
object is truly alive, or if it's a
zombie (i.e., a "living dead" object),
and just about every place you
construct one of your objects
(including within a larger object or
an array of objects) you need to check
that status flag via an if statement.
You'll also want to add an if to your
other member functions: if the object
is a zombie, do a no-op or perhaps
something more obnoxious.

In practice the "zombie" thing gets
pretty ugly. Certainly you should
prefer exceptions over zombie objects,
but if you do not have the option of
using exceptions, zombie objects might
be the "least bad" alternative.


A word of caution with throwing exceptions in a constructor:

Be very careful though because if an exception is thrown in a constructor, the class's destructor is not called. So you need to be careful about destructing objects that you already constructed before the exception is thrown. The same warnings apply to exception handling in general, but it is maybe a little less obvious when dealing with a constructor.

class B
{
public:
B()
{

}

virtual ~B()
{
//called after D's constructor's exception is called
}
};

class D : public B
{
public:
D()
{
p = new char[1024];
throw std::exception("test");
}

~D()
{
delete[] p;
//never called, so p causes a memory leak
}

char *p;
};

int main(int argc, char **argv)
{

B *p;
try
{
p = new D();
}
catch(...)
{

}

return 0;
}

Protected/Private constructors with CreateInstance method:

Another way around this is to make your constructor private or protected and make a CreateInstance method that can return errors.

c++, dealing with exceptions from constructors

One possibility is to wrap the construction and error handling in a function, returning the constructed object. Example :

#include <string>

class my_class {
public:
my_class(std::string path);
};

my_class make_my_object(std::string path)
{
try {
return {std::move(path)};
}
catch(...) {
// Handle however you want
}
}

int main()
{
auto my_object = make_my_object("this path doesn't exist");
}

But beware that the example is incomplete because it isn't clear what you intend to do when construction fails. The catch block has to either return something, throw or terminate.

  • If you could return a different instance, one with a "bad" or "default" state, you could have just initialized your instance to that state in my_class(std::string path) when it was determined the path is invalid. So in that case, the try/catch block is not needed.
  • If you rethrow the exception, then there is no point in catching it in the first place. In that case, the try/catch block is also not needed, unless you want to do a bit of extra work, like logging.
  • If you want to terminate, you can just let the exception go uncaught. Again, in that case, the try/catch block is not needed.

The real solution here is probably to not use a try/catch block at all, unless there is actually error handling you can do that shouldn't be implemented as part of my_class which isn't made apparent in the question (maybe a fallback path?).

exception handling a constructor

See this GOTW Constructor Failures question which addresses your query somewhat and goes on to say it is a waste of time.

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!

Error handling in C++, constructors vs. regular methods

In C++ exceptions is the way to report errors. BTW exception in initialization list CAN be handled.

A function-try-block associates a handler seq with the
ctor-initializer, if present, and the function-body. An
exception thrown during the execution of the initializer expressions
in the ctor-initializer or during the execution of the function-body
transfers control to a handler in a function-try-block in the same
way as an exception thrown during the execution of a try-block
transfers control to other handlers.

Good code usually should use minimum of try/catch blocks on most upper (thread) level. Ideally only one. This way, knowing that "everything throws", you have not think too much about errors and your normal scenario code flow looks clean.

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.

How should errors be handled when creating RAII classes?

The recommended course of action is to throw an exception on any failure that occurs during construction. Quoting the C++ FAQ:

Q. How can I handle a constructor that fails?

A. Throw an exception.

Constructors don’t have a return type, so it’s not possible to use return codes. The best way to signal constructor failure is therefore to throw an exception. If you don’t have the option of using exceptions, the “least bad” work-around is to put the object into a “zombie” state by setting an internal status bit so the object acts sort of like it’s dead even though it is technically still alive.

If construction involves RAII then the constructor has the additional responsibility to cleanup any already allocated resources prior to throwing.

Q. How should I handle resources if my constructors may throw exceptions?

A. Every data member inside your object should clean up its own mess.

If a constructor throws an exception, the object’s destructor is not run. If your object has already done something that needs to be undone (such as allocating some memory, opening a file, or locking a semaphore), this “stuff that needs to be undone” must be remembered by a data member inside the object.

As to why std::fstream constructors do not throw exceptions and use the fallback option by default (put the object into a “zombie” state), that is a combination of history and convenience, better explained in the answers to Why are C++ STL iostreams not “exception friendly”?.



Related Topics



Leave a reply



Submit