【问题标题】:C++ - Avoiding memory leak with exceptionsC++ - 避免异常的内存泄漏
【发布时间】:2014-07-31 18:36:55
【问题描述】:

假设你有一些这样的代码:

void myFunction()
{
    myClass * mine = new myClass();
    // body of function
    delete mine;
}

如果在函数体中抛出异常,delete 将永远不会被调用,并且会导致内存泄漏。除了使用<memory> 中的任何托管指针之外,缓解这种情况的最佳方法是什么。

【问题讨论】:

  • 编写自己的托管指针类? (注意:不要。使用现有的实现。)
  • 创建自己的类来管理指针。
  • 您对使用久经考验的托管指针有何不满?
  • std::auto_ptrstd::unique_ptr (C++11) 是要走的路。
  • 这就是为什么你应该在析构函数中释放内存

标签: c++ pointers memory-management memory-leaks exception-handling


【解决方案1】:

使用 RAII。有很多方法可以做到这一点,最好是使用久经考验的解决方案,例如std::unique_ptr<myClass>boost::scoped_ptr<myClass> 等智能指针。

如果您想自己完成实施 RAII 解决方案的练习,可以采用范围保护的形式:

struct guard
{
  myClass* ptr;
  guard(myClass* p) : ptr(p) {}
  ~guard() { delete ptr; }
  guard(const guard&) = delete;
  guard& operator=(const guard&) = delete;
};

请注意,RAII 要求代码在某个级别位于 try 块中。

【讨论】:

  • 使用智能指针是解决这个问题的唯一方法吗?有没有办法使用原始指针?
  • @user2612743 我刚刚给了你另一个解决方案。范围守卫。
【解决方案2】:

使用 std::auto_ptr 或(使用 C++11)std::unique_ptr 可以轻松避免此类内存泄漏:

#include <memory>

void myFunction()
{
    std::unique_ptr<myClass> mine(new myClass());
    // Use mine as before, mine->foo() or *mine is totally valid
    // The instance of myClass is deleted as soon as the unique_ptr goes out of scope
    // body of function
}

【讨论】:

  • 是的,我知道,但是有没有办法在不使用托管指针的情况下做到这一点?
  • 像 juanchopanza 说的那样定义你自己的类。但这很容易出错,基本上是“重新发明轮子”的情况。 std::unique_ptr 是一个非常轻量级的封装。当您谈论托管指针时,您几乎总是指std::shared_ptr,它引入了引用计数等开销。
  • is there anyway to do it without using managed pointers 即使使用自制代码,您也在“管理指针”。
【解决方案3】:

没有智能指针的管理方法是可用的,但不推荐:

void myFunction()
{
    myClass * mine = 0;
    try {
        mine = new myClass();
        // body of function
    }
    catch(...) {
        delete mine;
        throw;
    }
    delete mine;
}

同样,这种方法更容易出错(代码重复等),RAII 是首选,如前所述。

【讨论】:

  • 如果 STL 不可用(即在某些微控制器上),我想这是正确的答案
【解决方案4】:

您的第一选择应该是根本不使用new。在您的精简示例中没有任何内容表明堆栈分配会失败:

void myFunction()
{
    myClass mine;
    // body of function
}

如果您确实需要在堆上分配,那么更喜欢使用 RAII 包装器(更喜欢标准库中的包装器而不是自定义包装器)或 try/catch 结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-19
    • 2012-09-23
    • 2010-10-31
    • 2018-04-08
    • 2013-06-24
    • 1970-01-01
    相关资源
    最近更新 更多