简体   繁体   中英

Why do I have to free 2D array twice to avoid memory leak?

I am running into a memory leak problem when allocating a 2D array.
But I could not understand why the memory leaks.

My reasoning is that at Note A, I have already freed allocated memory, since data_[0] == data_ , why do I have to do the free at Note B?

class Matrix {
public:
  Matrix(int r, int c) {
    this->rows = r;
    this->cols = c;
    data_ = new int*[r];
    for (int i = 0; i < r; i++) {
      data_[i] = new int[c];
    }
  }

  ~Matrix() {
    for (int i = 0; i < this->rows; i++) {
      delete [] data_[i]; // Note A;
    }
    delete[] data_; // Note B; <-- not doing this line will leak memory, but why?
  }
private:
  int rows;
  int cols;
  int **data_;
};

What you post there isn't really a 2D array, it's a 1D array-of-pointers ( data_ ), and then you allocate a separate array-of-ints for each element of the first array (so data_[0] is an array of c ints, data_[1] is an array of c ints, and so on).

Given that, it's natural that you'll have to do one delete[] in your destructor for each new that you performed earlier in your constructor.

A graphical diagram of your memory allocations and how they point to each other might look like this (if c==6 and you have set all of your arrays' integers to 0 ):

分配图

A real 2D array allocation would look like this: int * array2D = new int[6][8]; , but of course C++ only supports 2D arrays if the array-dimenions are compile-time constants, so that probably wouldn't solve the problem your Matrix class is meant to solve.

When you have created 2D array (for example 3x3), you have created 1 array with 3 elements, where each element is pointer to separate array. So to clear memory for this matrix you need to clear 4 arrays (3 rows and 1 array containing pointers). You can check how many times in your code you are calling new operator it will be r+1 times

data_ = new int*[r];// 1 time
for (int i = 0; i < r; i++ {
  data_[i] = new T[c]; // r times
}

Part I: The line data_ = new int*[r]; allocates and default initializes a dynamic array of int* through new, so you would need to provide a corresponding delete [] data_; for this line.

Part II: The line data_[i] = new int[c]; dynamically allocates and default initializes an int array and then the pointer to that first element is returned and stored as the data_[i] element. So here again you would need a corresponding delete [] data_[i]; to get rid of the memory leak. So these were the reasons why you need two separate delete [] . The process is as shown in the screenshot. Also note that the important thing is the default initialization. So the int array elements will not all have a value 0 as wrongly shown in the answer by @Jeremy Friesner. 截图1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM