C ++在不使用智能指针的情况下清理try catch块中的内存。

时间:2013-05-03 20:30:40

标签: c++ exception

我将Exceptions添加到现有代码库中。在此示例中,DoAction()函数会创建一些内存并调用抛出异常的子函数ExceptionFnk()

DoAction()函数需要清理在将异常传递给更高级别之前创建的内存,以便正确处理。

考虑以下代码

#include "stdafx.h"
#include <exception>
#include <string>    

class CFooBase {
    public:
        static unsigned int _id ; 
        CFooBase( )  { printf( "Created CFooBase (%d)\n", ++CFooBase::_id ); }
        ~CFooBase( ) { printf( "Destroy CFooBase (%d)\n", CFooBase::_id-- ); }
};
unsigned int CFooBase::_id ; 

class ExceptionBar: public std::exception 
{
    public:
        const char* what() const throw() { return std::string( "ExceptionBar").c_str() ; }
        int Get() { return 99; }
};

// this function just throws an exception. 
void ExceptionFnk() {
    throw ExceptionBar( ); 
}

void DoAction() {

    CFooBase * b = new CFooBase();          
    ExceptionFnk(); 
    delete b; 

}


int _tmain(int argc, _TCHAR* argv[])
{
    try {
        DoAction() ;
    }
    catch( ExceptionBar& e ) {
        printf( "Higher, Exception: %s, magic number %d\n", e.what(), e.Get() ) ; 
    } catch (...) {
        printf( "Catch all, should not happen.\n" ) ; 
    }

    return 0;
}

生成此输出:

Created CFooBase (1)
Higher, Exception: ExceptionBar, Magic number 99

我尽量不使用智能指针,因为它会使系统过于复杂。

我的问题是:

  • 如何在将异常传递到更高级别之前清除DoAction()中的内存,而不使用智能指针。 ?

3 个答案:

答案 0 :(得分:5)

void DoAction() {
  CFooBase * b = new CFooBase();          
  try
  {
      ExceptionFnk();
  }
  catch(...)
  {
     delete b;
     throw;
  }
  delete b; 
}

答案 1 :(得分:5)

您可以删除SBRM-guard:

#include <type_traits>

template <typename T>
struct sbrm_deleter
{
    static_assert(std::is_array<T>::value == false,
                  "Must use unsized array type");

    T * ptr;
    sbrm_deleter(T * p = nullptr) : ptr(p) { }
    sbrm_deleter(sbrm_deleter const &) = delete;
    sbrm_deleter & operator=(sbrm_deleter const &) = delete;
    ~sbrm_deleter() { delete ptr; }
};

template <typename T>
struct sbrm_deleter<T[]>
{
    T * ptr;
    sbrm_deleter(T * p = nullptr) : ptr(p) { }
    sbrm_deleter(sbrm_deleter const &) = delete;
    sbrm_deleter & operator=(sbrm_deleter const &) = delete;
    ~sbrm_deleter() { delete [] ptr; }
};

用法:

{
    CFooBase * b = new CFooBase;
    sbrm_deleter<CFooBase> _(b);

    // dangerous code
    // don't say "delete" manually
}

答案 2 :(得分:0)

为什么不在堆栈上创建它?当抛出异常时,它将被堆栈展开清理:

void DoAction() {
    CFooBase b;          
    ExceptionFnk(); 
}