异常处理中的冗余代码

时间:2010-06-11 10:09:18

标签: c++

我经常遇到问题,我找不到一个优雅的解决方案来避免资源清理代码重复:

resource allocation:

try {
  f()
} catch (...) {
  resource cleaning code;
  throw;
}

resource cleaning code;
return rc;

所以,我知道我可以做一个清理析构函数的临时类,但我不喜欢它,因为它打破了代码流,我需要给类引用所有堆栈变量进行清理,功能相同的问题,我不知道如何不存在这个反复出现问题的优雅解决方案。

4 个答案:

答案 0 :(得分:8)

这个问题是RAII发明的原因。最佳做法是确保每个可释放资源都在对象内。或者,您可以使用Boost.ScopeExit或定义一个通用的sentinel类(在构造函数中接收仿函数并在析构函数中调用它的类)

编辑:在@Jackson指出的文章中,这称为ScopeGuard。通过将其与boost::functionboost::bind - 或std::tr1::functionstd::tr1::bind相结合,可以大大提高文章中的实施。

基本上,不是文章中的整个架构,您的实现将如下所示:

class scoped_guard
{
    boost::function<void(void)> atScopeExit;
public:
    scoped_guard(const boost::function<void(void)>& func) : atScopeExit(func) {}
    ~scoped_guard() { try { atScopeExit(); } catch(...) {} }
};

您可以通过添加解除它或其他东西的功能(在堆栈展开的情况下安全地捕获异常?)来进一步增强这一点吗?但是 我懒得这是留给读者的练习;)。

答案 1 :(得分:3)

答案 2 :(得分:2)

这篇Dr Dobbs文章可能会有所帮助。

答案 3 :(得分:0)

你需要自我释放的资源,这真的不难做到。

对于内存使用autopointers,STL,Boost或自己制作,这并不难。

对于文件,最好使用std :: fstream。如果你必须使用fopen或CreateFile(或其他)创建一个简单的句柄类,在破坏时调用适当的close函数。

与任何其他资源类似,构建一组智能句柄类。