views:

438

answers:

6

Hi

I have one question about failed constructor and failed destructor in C++.

I noticed that when the constructor failed, an exception will be thrown. But there is no exception thrown in destructor.

My question is

1) If constructor failed, what exception will be thrown? bad_alloc? or anything else related? Under what situation, a constructor would fail? What about the successfully constructed part?

2) Under what situation, a destructor would fail? If no exception is thrown, what would happen to the destructor? How does the compiler deal with it? What's the return value to the function it is called?

Thanks!

Any comments are strongly appreciated!

+1  A: 

Constructor in this context is "just" a user function, it can throw any exceptions it wants. If a constructor doesn't throw an exception, it's considered not be failed.

So: a constructor doesn't fail on its own. If it throws an exception itself, it failed. If it doesn't, no special code is implicitly added by compiler to throw any exceptions.

The same is true for destructors, too.

Vlad
+5  A: 
  1. If a constructor fails, an exception is thrown only if the constructor is implemented so that it throws an exception. (You might need to differentiate between memory allocation and construction. Allocating memory using new might fail throwing a std::bad_alloc exception.)

  2. There is no case where a constructor, in general, fails. It fails only if it is written so that it might fail. If so, how it fails depends on how it is written. In general, destructors should be written so they don't fail, as it is not safe to throw exceptions from destructors. (That's because they might be called during stack unwinding.)

Note that "failing" as used in your question generally refers to runtime failures. So the compiler has nothing to do with it. Also, neither constructors nor destructors return anything.

sbi
+1 :) Tho many RAII classes cannot be written no-throw i think, because they often release external resources. One will need to write a try-catch block around these release ops to ensure the exception won't escape. (Maybe having a guaranteed no-throw logging mechanism to log this failure?).
Johannes Schaub - litb
@Johannes: Note that I wrote "...in general ... should be...". `:)`
sbi
+1  A: 

The exception that is thrown when a constructor fails is determined by the constructor itself, either because it throws directly, or by the actions it takes (like calling another function that might throw an exception).

Constructors can fail when they try to acquire a resource that is not available, like memory, a file handle, a screen window, etc. If new fails, it'll throw std::bad_alloc. If the constructor doesn't catch it, then that will propagate out of the constructor.

C++ has no good way to deal with errors in a destructor. To the extent possible, you should design destructors to not fail. You should never throw an exception from a destructor. And if a function you call in a destructor might throw an exception, you should either catch it (if you know it's safe to ignore) or crash immediately.

Adrian McCarthy
+2  A: 

If your destructor throws an exception you're doing something wrong. Throwing an exception in the destructor can lead to several problem areas: items used from socket/thread/object pools may become permanently trapped in an unretreivable state, memory may not be deallocated, or logic which for some reason you placed in the destructor may not get called.

All the same reasons that an exception might get thrown in code elsewhere can cause an exception to be thrown in a destructor. Most notably if you've got a dangling pointer somewhere attempting to clean up currently used memory can cause a system exception. Good luck handling that.

wheaties
+1  A: 

If a constructor fails, well, it throws some exception. It doesn't have to be because memory couldn't be allocated; anything else that would throw an exception will make it fail, and that includes throw statements you write yourself. The idea is generally either to create a usable object or throw an exception.

If a constructor fails, there is no successfully constructed part. It's all gone.

I don't know what is meant by a destructor failing. It will execute any applicable code, and doesn't return anything. If the code is badly written, it can fail to do what the programmer wants, but that's true of all functions.

Destructors should never throw exceptions. (They can call routines that throw, but they should catch all exceptions and deal with them themselves.) If a destructor throws, and it's called because an exception has been thrown and it's unwinding the stack, the program crashes, one way or another. (There are mechanisms to try to tell if the stack is unwinding or not, but at best you're writing a destructor two different ways, and it's hard to test both of them.)

David Thornley
+1  A: 

In addition to everything mentioned here, operator new can throw bad_alloc before it calls the constructor. The constructor only starts running after a piece of memory exists for the object instance to exist in (although it doesn't fully exist until the constructor finishes).

Ben Voigt