exception handling in the c++ constructor

4

Click here to load reader

Upload: somenath-mukhopadhyay

Post on 22-May-2015

1.142 views

Category:

Technology


1 download

DESCRIPTION

A discussion on the exception handling in the constructor of C++

TRANSCRIPT

Page 1: Exception Handling in the C++ Constructor

Exception handling at C++constructor

Somenath Mukhopadhyay

Its a very common problem in C++ that if a class's constructor throws an exception (saymemory allocation exception) how we should handle it. Think about the following piece of code.CASE I:class Aprivate: int i;//if exception is thrown in the constructor of A, i will de destroyed by stack unwinding//and the thrown exception will be caughtA()i = 10;throw MyException(“Exception thrown in constructor of A()”);

;void main()try

A();catch(MyException& e)

e.printerrmsg();

Here class A's constructor has thrown an exception.. so the best way to handle such situation isto instantiate A inside a try block...if exception is thrown in the constructor of A, i will be destroyedby stack unwinding and the thrown exception will be caught... try­catch block in exception is veryimportant as constructor cannot return anything to indicate to the caller that something wronghas happened...CASE IILets consider the following case.

Page 2: Exception Handling in the C++ Constructor

class Aprivate:char* str1;char* str2;A()str1 = new char[100];str2 = new char[100];Here in class A we have two dynamically allocated char array. Now suppose while constructingA, the system was able to successfully construct the first char array, i.e. str1. However, whileallocating the memory of str2, it throws OutOfMemory exception. As we know the destructor ofan object will be called only if the object is fully constructed. But in this case the object is not fullyconstructed. Hence even if we release the memory in the destructor of A, it will never be called inthis case. So what we will have is that the stack based pointers, i.e. str1 and str2 will be deletedbecause of stack unwinding. But the memory that have been allocated in the Heap won’t bedestroyed. Hence we will have two blocks of heap memory ( one for the str1 that is 100 byteslong and the other for whatever have been allocated by str2 before the exception being thrown)which are not referenced by any pointer (str1 and str2 which have already been destroyed by thestack unwinding). Hence it is a case of memory leak.Now the question is how can we handle the above situation. We can do it as follows.

class Aprivate:char* str1;char* str2;A()trystr1 = new char[100];catch (...)delete[] str1;throw(); //rethrow exceptiontrystr2 = new char[100];catch(...)delete[] str1;delete[] str2;throw(); //rethrow exception

Page 3: Exception Handling in the C++ Constructor

But the best way to handle this kind of situation in modern C++ is to use auto_ptr/shared_ptr.Look at the following piece of code to know how we have used boost’s shared pointer to avoidmemory leaks in the C++ constructor.

#include <iostream>#include <string>#include <memory>#include <boost/shared_ptr.hpp>#include <boost/shared_array.hpp>using namespace std;class SomeClasspublic:

SomeClass()~SomeClass();

;typedef boost::shared_ptr<SomeClass> pSomeClass;typedef boost::shared_ptr<cha> pChar;typedef boost::shared_array<char> pBuffer;class MyExceptionpublic:

MyException(string str)msg = str;void printerrmsg()

cout<<msg.c_str<<endl;

private:string msg;

;class Aprivate:

int i;pChar m_ptrChar;pSomeClass m_ptrSomeClass;pBuffer m_pCharBuffer;

public:A():m_ptrChar(new char),m_ptrSomeClass(new SomeClass),m_pCharBuffer(new

char[100])i = 10;throw MyException("Exception at A's constructor");

Page 4: Exception Handling in the C++ Constructor

;In Symbian C++, it is handled by a concept called two phase constructor... (it came into thepicture because there was no template concept in earlier Symbian C++, and hence there wasno auto_ptr)... in this process, if we want to create a dynamic memory allocation at the heappointed by say *pMem, then in the first phase of construction we initialize the object pointed bypMem;. obviously this cannot throw exception... We then push this pMem to the cleanup stack...and in the second phase of construction, we allocate memory pointed by pMem... so, if theconstructor fails while allocating memory, we still have a reference of pMem in the cleanupstack... we just need to pop it and destroy it... hence there is no chance of memory leak...

EXCEPTION CLASS#include <iostream>#include <string>#include <memory>

class MyException(string str)private:

string msg;public:

MyException(string str)msg = str;void printerrmsg()cout<<msg.c_str()<<endl;