【问题标题】:Copy assignment operator memory leak, on big project复制赋值运算符内存泄漏,在大项目上
【发布时间】:2015-06-26 08:55:40
【问题描述】:

在过去的几个月里,我一直在做一个大项目。现在我终于完成了那个项目。但是在我的复制赋值运算符中,我有内存泄漏。 Valgrind 表明泄漏的是 data_ 的原始值。

这是我的复制赋值操作符代码。

Value& Value::operator=(const Value& r)
{
  data_ = copy(r.data_);
  delete data_; 
  return *this;
}

谁能帮我解决这个问题?我真的很感激。

【问题讨论】:

  • 什么是data_?我想是一个指针......但为什么它被复制(它是std::copy?)并被删除。 *this 是什么,我在那里看不到任何课程

标签: c++ memory-leaks copy variable-assignment operator-keyword


【解决方案1】:

我相信你想写这个:

delete data_;     //here it makes sense: delete the current value
data_ = copy(r.data_);  //copy now

不是这个:

data_ = copy(r.data_); //LEAK, as data_ is pointing to current value
delete data_;         //here you're deleting the copied one

确保data_ 始终指向有效内存——否则有条件地删除它。

【讨论】:

  • 是的,当然!我只是代码盲。谢谢帮助的小伙伴! :)
【解决方案2】:

这没有意义:

data_ = copy(r.data_);
delete data_; 

因为如果data_ 指向分配的内存,而您覆盖它

data_ = copy(r.data_);

然后然后删除新复制的区域,你有内存泄漏(你不能再引用你原来分配的内存)。

删除刚刚复制的内存的一大好处:如果你曾经实际使用过_data 指针,你会得到未定义的行为。

你可能打算写

template <typename T>
Value<T>& Value<T>::operator=(const Value<T>& r)
{
  delete data_; // Free this object's memory
  data_ = copy(r.data_); // And now get a copy (hopefully a deep one) of the new memory
  return *this;
}

一个小警告:上面的代码即使修复了没有强异常保证:如果内存复制由于任何原因失败,您最终可能会得到一个不一致的对象(因为 data_ 已经已删除)。

【讨论】:

    【解决方案3】:

    问题data_被复制后立即被删除!

      data_ = copy(r.data_);
      delete data_;          <<< PROBLEM
    

    最好的解决方案可能是使用复制和交换习语 (What is the copy-and-swap idiom?)。

    template <typename T>
    Value<T>& Value<T>::operator=(const Value<T> rhs)  // NOTE: pass by value
    {
      swap(data_, rhs.data_);  // either std::swap or a custom swap,
                               // hard to say without knowing the type of data_
      return *this;
    }
    

    另一种选择,直接增强 OP 的代码,可能如下。

    template <typename T>
    Value<T>& Value<T>::operator=(const Value<T>& r)
    {
      // 1) Allocate new data. If, for some reason, the allocation throws,
      // the original data_ stays intact. This offers better
      // exception safety.
      ... new_data = ...;
    
      // 2) Copy r.data to new_data (note: deep copy desired)
      new_data = copy(r.data_); 
    
      // 3) Destroy original data_
      delete data_;
    
      // 4) Point data_ to new_data
      data_ = new_data;
    
      return *this;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-10-16
      • 2016-05-08
      • 1970-01-01
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 2017-11-21
      相关资源
      最近更新 更多