0

根据 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_;
}
4

2 回答 2

2

代码中有几处不好:

IE

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;
  }
}
于 2013-09-24T18:55:11.707 回答
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。除非类的析构函数清理了 values_。

于 2013-09-24T18:52:19.347 回答