在大项目上复制赋值操作符内存泄漏

时间:2015-04-19 18:43:39

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

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

这是我的副本分配操作员代码。

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

任何可以帮我解决这个问题的人?我真的很感激。

3 个答案:

答案 0 :(得分:5)

我相信你想写这个:

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_始终指向有效的内存 - 否则有条件地删除它。

答案 1 :(得分:1)

这没有意义:

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_已经已被删除)。

答案 2 :(得分:0)

问题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;
}