1

I came across a situation where constructor allocated the dynamic memory and if any exception occurs in the constructor, it was not freeing the dynamically allocated memory. To avoid such situation I used unique_ptr, and it is able to free the memory properly.

To showcase the situation here is a dummy code for that.

class ExceptionInConstructor
{
 unique_ptr<int> a;
public:
    ExceptionInConstructor()
    {
        a = std::unique_ptr<int>( new int(10));
        cout <<"Constructor called. Value of a is "<< *a<<endl;
        //some exception occurs after the mrmory allocation
        throw exception();
    }
    ~ExceptionInConstructor()
    {
        cout << "Dest called()"<<endl;
    }
};

int main()
{ 
    try
    {       
        ExceptionInConstructor ex; 
    }
    catch(...)
    {}  
    return 0;
 }

Is it a correct and efficient way for such a situation or is there any better option for such a scenario?

Edit 1: Removed the commented code in destructor which was left by mistake

santosh kumar
  • 585
  • 4
  • 14
  • 3
    That's exactly the purpose of using smart pointers. _" it was not freeing the dynamically allocated memory. "_ How (which tool) did you use to observe that? – πάντα ῥεῖ May 26 '19 at 10:12
  • ... and the RAII idiom in general – StoryTeller - Unslander Monica May 26 '19 at 10:13
  • 1
    In the particular case you show, there is no need. When the exception is thrown, the destructor of `unique_ptr` releases the object `a` and the dynamically allocated object (from `new int (10)`) that it manages. As far as `main()` is concerned, once the exception is thrown, the object `ex` never existed. It is generally considered better to initialise the member `a` in the constructor's initialiser list, rather than in the constructor body, though. – Peter May 26 '19 at 10:16
  • [The rule of zero](https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_zero) and [RAII](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization) helps solve this problem very nicely. – Some programmer dude May 26 '19 at 10:27
  • @WhozCraig: OP uses `std::unique_ptr` (and not `unique_ptr`) (and use it as is) so it seems intended. – Jarod42 May 26 '19 at 12:28
  • Maybe related: https://stackoverflow.com/q/10212842/4944425 – Bob__ May 26 '19 at 12:36
  • @πάνταῥεῖ, I used MS Visual Studio in debug mode and confirmed without a smart pointer, it is not releasing the memory allocated for integer – santosh kumar May 26 '19 at 12:55
  • @santoshkumar without a smart pointer, the memory won't be released *regardless* of whether an exception is thrown unless you *specifically* do so (and there's no place to do so unless you try/catch in the ctor). The order of operations in throwing out of a constructor is specific. Nothing that didn't complete its constructor *ever* has its destructor fired. Your object did not complete construction, but the members *did*. Their destructors are fired in reverse order of member decl in the class. For a simple pointer, that amounts to nada. A smart pointer member will release it's goods. – WhozCraig May 26 '19 at 16:46

1 Answers1

1

No, that is exactly the point and intended use case for smart pointers and RAII in general.

Also note that your delete a in your destructor is wrong in any case as the unique_ptr is not a pointer itself. Relatedly, destructors are also not called if there is an exception in the constructor.

Stephan Dollberg
  • 32,985
  • 16
  • 81
  • 107
  • "delete a" was left by mistake added for the case where it was not with smart pointer, which I removed it. @inf Yes, I understand that destructor won't be called in case of exception in the constructor. That was the reason why it was not freeing the memory allocated for int variable without uniqe_ptr. – santosh kumar May 26 '19 at 16:19