What happens when constructor throws excetpion

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
Not valid. You define obj within the "try" {}'s. You cannot use obj outside them.
Thanks !
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?
What do you mean by "Release the acquired resource" ?
Probably you don't need to do anything.
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.
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
thanks to you all
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");
    }   
}

@Cubbi

Can you elaborate some more view on how to handle the case if I have pthread_mutex.
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
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 ?
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
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
Topic archived. No new replies allowed.