Exception-safe code.

Hello,

I am reading Exceptional C++ and, in item 8, I found this:
1
2
3
4
Stack::Stack(): v_(0), vsize_(10)
{
  v_ = new T[vsize];
}

The book says that the above function is exception-safe, for two reasons:
1. If operator new throws a bad_alloc exception no memory has been allocated thus no leaks.

2. If one of the T constructors throws an exception, the T objects previously constructed will be delete via delete[].

I don't understand point 2. The deconstructor of Stack will never be called if one of the T's throws an exception thus who is going to delete them?

Last edited on
closed account (oz10RXSz)
New operator for arrays takes care of this. If some of the array element constructors throws, the memory allocated for the array is deleted. Then, the exception is passed up to the caller of new.
If the Stack constructor is called by the new e.g.:

 
Stack::Stack* s = new Stack::Stack();


This new will catch the exception, and deallocate the memory for stack, so no memory leak will occur, and rethrow. If the Stack object was allocated on the stack, normal rules for handling exceptions apply (the stack is unwound, destructors are called - no memory leak).

Nevertheless, according to Google style guide, constructors should not allocate memory / resources, because in more complex programs it is difficult to proove exception-safety. On the other side, constructors creating objects in illegal state, and requiring a special call to "init", contradict basic rule of OOP - that objects should be created always in valid state.

BTW: On some platforms new does not raise exceptions. E.g. on Linux you won't get it. New will pass, even if there is not enough physical memory - your app will get killed when you try to initialize this memory (probably somewhere in the constructor - but this will not be a catchable exception).
Last edited on
yeah, I think the implementation of new operator is something like:

1
2
3
4
5
6
7
8
9
10
11
12
  void* pBuffer = operator new(sizeof(Foo)*n);
  Foo* pFoo = static_cast<Foo*>(pBuffer);
  try {
    for(i = 0; i < n; ++i) {
      new (pFoo+i) Foo;
    }
  }
  catch (...) {
    while(--i >= 0) {
      pFoo[i].~Foo();
    }
  }
Topic archived. No new replies allowed.