我将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()
中的内存,而不使用智能指针。 ?答案 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();
}