What happens when constructor throws excetpion

Jun 12, 2012 at 8:14pm
Hi,

what will happen if class constructor throw an exception?

1
2
3
4
5
6
try {
    MyClass obj;
}
catch(...) {
}
obj.Function(); // Is this statement will be valid then? 


Also if this obj happens to be valid do I need to call destructor of this class? As this class might have acquired some resource/handle?

thanks
Jun 12, 2012 at 8:28pm
Not valid. You define obj within the "try" {}'s. You cannot use obj outside them.
Jun 12, 2012 at 8:34pm
Thanks !
Jun 12, 2012 at 8:35pm
But what If I've created that constructor?
I mean before throwing the exception do I need to release the acquired resource?

How could I handle that case?
Jun 12, 2012 at 8:37pm
What do you mean by "Release the acquired resource" ?
Probably you don't need to do anything.
Jun 12, 2012 at 8:37pm
There is nothing to release. The object hasn't been constructed completely yet if the constructor throws an exception. You'll need to deallocate any dynamic memory you've allocated in the constructor before throwing, however.
Jun 12, 2012 at 8:38pm
Is this statement will be valid then?


No. Aside from the scope issues (obj will be an undeclared identifier because it only exists inside the try block) -- if the constructor throws an exception, then the object is not constructed and must not be used.

Also if this obj happens to be valid do I need to call destructor of this class?


You should NEVER* manually call the destructor. The compiler does that automatically. Never* call it yourself.

*The only exception is if you are using placement new to construct an object in an already allocated area of memory. In which case, you would need to manually call the destructor so you can destroy the object without freeing the space.

But you probably aren't doing that, so just don't do it
Jun 12, 2012 at 8:44pm
thanks to you all
Jun 12, 2012 at 8:50pm
But what If I've created that constructor?
I mean before throwing the exception do I need to release the acquired resource?


Yes, *if* you acquired that resource directly, not through a RAII class.

e.g., bad style:

1
2
3
4
5
6
7
8
9
Foo::Foo() {
    pthread_mutex_lock(m); // raw resource acquisition
    // stuff happens 
    if(stuff went wrong)
    {
        pthread_mutex_unlock(m);
        throw std::runtime_error("stuff went wrong");
    }   
}

good style:

1
2
3
4
5
6
7
8
Foo::Foo() {
    std::lock_guard<std::mutex> lk(m); // RAII resource acquisition
    // stuff happens 
    if(stuff went wrong)
    {
        throw std::runtime_error("stuff went wrong");
    }   
}

Jun 12, 2012 at 8:56pm
@Cubbi

Can you elaborate some more view on how to handle the case if I have pthread_mutex.
Jun 12, 2012 at 9:41pm
closed account (zb0S216C)
When a constructor throws an exception, the object itself is never constructed; thus, it's unsafe to access anything within the class, even member functions. If a base-class throws an exception, the construction of all derived classes (including the base-class) fail, and again, they should not be accessed. If a constructor throws an exception during an allocation request, the accumulated memory is returned back to the heap/free-store. For instance:

1
2
3
4
5
6
7
8
9
10
11
#include <exception>

struct Object
{
    Object() { throw(std::bad_alloc()); }
};

int main()
{
    Object *NewObject(new Object());    
}

Here, the construction of the new Object will no doubt fail. This will cause new to return the memory it accumulated to store the object back to the heap/free-store. This behaviour prevents memory leaks.

Wazzak
Last edited on Jun 12, 2012 at 9:41pm
Jun 12, 2012 at 10:10pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class A {
public:
    A() {
        mFileHandle = fopen("SomeFile.txt", "w");
    }

    ~A() {
        if(mFileHandle) {
            fclose(mFileHandle);
            mFileHandle = NULL;
    }

    FILE*  mFileHandle;
};

class B : public A {
public:
    B(): A() {
        throw 1;
    }
    ~B() { }
};

class C : public B {
public:
    C() {}
    ~C() {}
};

int main() {
    C *c = NULL;
    try {
        c = new C();
    }
    catch (...) {
    }

    return 0;
}


what will happen here?

will c pointer will be valid ?
Jun 12, 2012 at 10:17pm
what will happen here?


1) A will be constructed
2) B's constructor will start, but will throw an exception
3) A will be destructed
4) Exception will be caught by the catch block

will c pointer will be valid ?


No. c will be NULL. The exception was thrown before the assignment completed, so it was never reassigned.

Remember that new needs to finish evaluating before the pointer can be assigned to c. In this case, since the exception is thrown before new completes, the assignment never happens.
Last edited on Jun 12, 2012 at 10:23pm
Jun 12, 2012 at 10:22pm
closed account (zb0S216C)
Yes, c will be invalid (if NULL is invalid to you) because the base-class B throws an exception during construction. As I've said before, if a base-class (B) throws an exception during construction, all derived classes (A) will fail to construct. Consequently, new will fail to construct an object and will free the memory it accumulated for the requested object.

Wazzak
Last edited on Jun 12, 2012 at 10:22pm
Topic archived. No new replies allowed.