使用2d数组指针的C ++内存泄漏

时间:2013-09-24 18:36:01

标签: c++ pointers memory memory-leaks delete-operator

根据Dr. Memory的说法,下面的三个函数在标有“// memory leak vvv”的行中包含内存泄漏。我对C ++和指针比较陌生,并且不确定为什么这些行会导致泄漏。 “values_”是T **,是UndoArray类的成员变量。

template <class T> void UndoArray<T>::set(size_type i, const T& v) {
    counts_[i]++;
    if(!initialized(i)) {
        // memory leak vvv
        values_[i] = new T[1];
        values_[i][0] = v;
    } else {
        // memory leak vvv
        T* temp = new T[counts_[i]];
        for(int j = 0; j < counts_[i] - 1; j++) {
            temp[j] = values_[i][j];
        }
        temp[counts_[i] - 1] = v;
        delete [] values_[i];
        values_[i] = temp;
    }
}

template <class T> void UndoArray<T>::undo(size_type i) {
    counts_[i]--;
    if(counts_[i] == 0) {
        values_[i] = NULL;
    } else {
        T* temp = values_[i];
        // memory leak vvv
        values_[i] = new T[counts_[i]];
        for(int j = 0; j < counts_[i]; j++) {
            values_[i][j] = temp[j];
        }
        delete [] temp;
    }
}

template <class T> void UndoArray<T>::copy(const UndoArray<T>& ua) {
    size_ = ua.size_;
    counts_ = new unsigned[size_];
    for(int i = 0; i < size_; i++) {
        counts_[i] = ua.counts_[i];
    }
    values_ = new T*[size_];
    for(int i = 0; i < size_; i++) {
        if(counts_[i] == 0) {
            values_[i] = NULL;
        } else {
            // memory leak vvv
            values_[i] = new T[counts_[i]];
            for(int j = 0; j < counts_[i]; j++) {
                values_[i][j] = ua.values_[i][j];
            }
        }
    }
}

UndoArray的构造函数使用...

template <class T> void UndoArray<T>::create() {
    size_ = 0;
    counts_ = new unsigned[size_];
    values_ = new T*[size_];
}

...如果调用默认构造函数(无参数)或...

template <class T> void UndoArray<T>::create(size_type n) {
    size_ = n;
    counts_ = new unsigned[size_];
    for(int i = 0; i < size_; i++)
        counts_[i] = 0;
    values_ = new T*[size_];
    for(int i = 0; i < size_; i++)
        values_[i] = NULL;
}

...如果指定了初始数组大小。

析构函数看起来像......

template <class T> UndoArray<T>::~UndoArray() {
    delete [] counts_;
    if(values_ != NULL) {
        for(int i = 0; i < size_; i++) {
            delete [] values_[i];
        }
    }
    delete [] values_;
}

2 个答案:

答案 0 :(得分:2)

代码中有几件不合适的东西:

template <class T> void UndoArray<T>::copy(const UndoArray<T>& ua) {
size_ = ua.size_;
counts_ = new unsigned[size_];
for(int i = 0; i < size_; i++) {
    counts_[i] = ua.counts_[i];
}
//What if values_ is not null here? You do not delete the old data
values_ = new T*[size_];

在您发布的代码中,您可以执行类似的操作。

Edit1:给你另一个例子

template <class T> void UndoArray<T>::undo(size_type i) {
counts_[i]--;
if(counts_[i] == 0) {
    //what if values_[i] != nullptr here? You will leak the old value...
    values_[i] = NULL;

当然,您应该确保删除析构函数中的每个指针。

像:

~UndoArray()
{
  if (nullptr != values_)
  {
      for (int i = 0; i < size_; ++i)
      {
         delete [] values[i];
      }

      delete [] values;
  }
}

答案 1 :(得分:0)

template <class T> void UndoArray<T>::set(size_type i, const T& v) {
    counts_[i]++;
    if(!initialized(i)) {
        // memory leak vvv`

这是泄漏,因为从不删除values_ [i]。

    values_[i] = new T[1];
    values_[i][0] = v;
} else {
    // memory leak vvv

这里的问题相同。没有删除临时;言。

    T* temp = new T[counts_[i]];
    for(int j = 0; j < counts_[i] - 1; j++) {
        temp[j] = values_[i][j];
    }
    temp[counts_[i] - 1] = v;
    delete [] values_[i];
    values_[i] = temp;
}

您必须在新内存上调用delete。除非类的析构函数清除值_。