Sep 20, 2011

auto_ptr and shared_ptr for resource management


Resource management is common troublesome issue for C/C++ programmer. If you don't free a resource that you acquire, you will run out of resource some day.

Scott Meyers, the author of Effective C++, recommended RAII(Resource Acquisition Is Initialization) for resource management. There are several ways to do it but simple way is to use auto_ptr and shared_ptr if your concern is about memory.

Give you a couple of example.

In this example, an error occurs before you delete an object that you acquirer, so resource leak happens. So you have to care about somebody except you because he can write a code that resource leak happens.

Investment* createInvestment() {
  return new Investment;
}

// an example of memory leak                                                                              
void f1(){
  std::cout << "f1" << std::endl;
  try {
    Investment *pInv = createInvestment();

    //If some one write code that can throws error,                                                       
    //destructor of Investment may not be called.                                                         
    throw 1;

    delete pInv;
  } catch(...) {
    std::cout << "catch" << std::endl;
  }
}

In this example, I used auto_ptr for resource management. Now you don't need to care about resource. When the control flow leaves the scope, auto_ptr frees a pointer.

//an example of auto_ptr                                                                                  
void f2(){
  std::cout << "f2" << std::endl;

  try {
    //If you pass a pointer to auto_ptr,                                                                  
    //auto_ptr frees it when the control flow leaves the scope.                                           
    std::auto_ptr pInv(createInvestment());
    throw 1;
  } catch (...) {
    std::cout << "catch" << std::endl;
  }
}

auto_ptr has several limitation. For example several auto_ptr cannot contain the same pointer. So you cannot put auto_ptr into STL container because STL container assume that every object can copy.

void f3(){
  std::cout << "f3" << std::endl;
  //several auto_ptr cannot contain the same pointer.                                                     
  //If you copy auto_ptr, then the source becomes null pointer and                                        
  //the destination can contain the pointer.                                                              
  Investment* pInv1 = createInvestment();
  std::auto_ptr pInv2(pInv1);
  std::auto_ptr pInv3(pInv2);
}

If you need to contain the same pointer with several auto_ptr, you should use shared_ptr in Boost Libraries. But shared_ptr has limitation. You cannot use it for an array.

void f4(){
  //several shared_ptr objects can have the same pointer.                                                 
  boost::shared_ptr pInv1(createInvestment());
  boost::shared_ptr pInv2(pInv1);

  //If every shared_ptr objects are freed, then the pointer                                               
  //that they have also freed.                                                                            
}


Here is a sample code for this entry.
https://github.com/yohei1126/effectivecpp/blob/master/chap3/term13/Investment.cpp

There are other ways for resource management. I will write it some day :)

No comments:

Post a Comment