1

我正在将异常添加到现有代码库中。在此示例中,该函数会增加一些内存并调用引发异常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()在不使用智能指针的情况下,如何在将异常传递给更高级别之前清理内存。?
4

3 回答 3

5
void DoAction() {
  CFooBase * b = new CFooBase();          
  try
  {
      ExceptionFnk();
  }
  catch(...)
  {
     delete b;
     throw;
  }
  delete b; 
}
于 2013-05-03T20:31:55.217 回答
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
}
于 2013-05-03T20:33:58.327 回答
0

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

void DoAction() {
    CFooBase b;          
    ExceptionFnk(); 
}
于 2013-05-03T21:55:54.087 回答