What's the Best Technique for Exiting from a Constructor on an Error Condition in C++

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.

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.

How to end C++ code directly from a constructor?

You should throw an exception, when the constructor fails, like this:

B() {
if(somethingBadHappened)
{
throw myException();
}
}

Be sure to catch exceptions in main() and all thread entry functions.

Read more in Throwing exceptions from constructors. Read about Stack unwinding in How can I handle a destructor that fails.

C++ : handle resources if constructors may throw exceptions (Reference to FAQ 17.4]

There is a similar question here that covers what your asking.

In this case, if the call to new fails, then the memory for the pointer is guaranteed to be freed. If the call succeeds, and the constructor throws after that, you will have a memory leak.

The destructor of the class will not be called, because the object was never fully constructed. There are two ways to fix this.

1)

Have exceptions fully managed in the constructor:

class Foo
{
public:
Foo()
try
{
p = new p;

throw /* something */;
}
catch (...)
{
delete p;

throw; //rethrow. no memory leak
}
private:
int *p;
};

2)

Or use a smart pointer. When a constructor is entered, all of its members have been constructed. And because when a constructor throws, and objects members have been constructed, they must be destructed. And a smart pointer fixes that:

class Foo
{
public:
Foo() :
p(new int)
{
throw /* something */;
}
private:
std::auto_ptr<int> p;
};

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.

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.



Related Topics



Leave a reply



Submit