CAUTION!

CAUTION! DANGER ZONE ahead. Beware of misinformation on the open internet. Contents of the site are mere opinions and are not always facts!

Monday, April 13, 2015

RAII- Resource Acquisition Is Initialization

In C++, there is no automatic memory management/ Garbage collection which causes memory leaks. Unused memory should be deleted manually. Similarly, other resources not released even if not used causes resource leaks.

RAII is a commonly used OOP idiom to carefully manage resources. It is a scope based resource management style where the resource is acquired at the beginning of the scope and released at the end of the scope. The scope can be a block, a function or a class. The resources can be memory, files, mutexes etc

With RAII, The resources are acquired in the constructor and released in the destructor of the resource management class, so that the objects of this class can be declared in the required scope and the resources are re-claimed via the destructor when the objects go out of scope.

Here is an example of managing the memory with RAII. Do note that every class can do this management on its own. This example demonstrates RAII along with single responsibility principle. And so a class is exclusively written to manage the memory.

//Example for POD type. parameters for object construction and member access operator (->) are not considered.

template<typename T>
class CManagedMemory
{
     T *m_memory;
     CManagedMemory()
     {
          m_memory = new T(); // no more wild pointers!
     }
     //used for r value
     operator T()
     {
          return *m_memory;
     }
  
     // used for l value
     T operator=(T rVal)
     {
          *m_memory = rVal;
           return rVal;
     }
   
     ~CManagedMemory()
     {
          delete (m_memory);
          m_memory = NULL; // no more dangling pointers!
     }
};
The benefits of RAII are,

1. There are no resource leaks.

2. The resource variable is initialized to a valid state as soon as it is created and reset as soon as it is deleted.
    For example, a pointer which is not initialized - wild pointer - will have garbage value (pointing to a random address) or a pointer which is deleted - dangling pointer - points to reusable memory causes unexpected behavior. With RAII, the pointer is initialized when the managed memory object is declared.
    Without RAII,
 int *ptr; // contains garbage value
 delete(ptr); // contains dangling value

3. Custom define resource sharing, by appropriately declaring custom copy constructor, assignment operator as either private or public.

4. Resource is released automatically as soon as it is no longer needed. when the managed resource object goes out of scope, the destructor of the object releases the resource.
    Without RAII,
{
     int *ptr = new int();
}// memory leak. ptr should be deleted before the end of the block.
    With RAII,
{
     CManagedMemory<int> ptr;
}// memory deleted automatically

5. Resource reclaimed even on exceptions.
     Without RAII,
{
     int *ptr = new int();
     *ptr = 100 / 0; // divide by zero exception. Statements after this statement are not executed.
     delete (ptr);
}
    With RAII,
{
     CManagedMemory<int> ptr;
     ptr = 100 / 0; // divide by zero exception.
}// memory deleted even when the exception is thrown.

6. Code cleanliness. The code to reclaim the resource is in one place, in the destructor. The code need not be written in every procedure call or every branch.

C++11 introduces smart pointers like unique_ptr (no memory sharing), shared_ptr (shared memory) and weak_ptr for managing memory with RAII.

No comments:

Post a Comment