Destructor

I construct a 2D array Space**_board as follow
enum Space {RedDisc, YellowDisc, Empty};
Space **_board;
ConnectN::ConnectN(int n){
_board= new Space*[BOARD_HEIGHT];
for (int i = 0; i < BOARD_HEIGHT; i++)
_board[i] = new Space[BOARD_WIDTH];

for(int i=0;i<BOARD_HEIGHT;i++){
for(int j=0;j<BOARD_WIDTH;j++){
_board[i][j]=Empty;
}}
}

But why i cannot have a Destructor as
ConnectN::~ConnectN(){
for (int i = 0; i < BOARD_HEIGHT; i++)
delete []_board[i];
delete []_board;
}

it fails to free the array of pointers.
what should be in the Destructor?
i have tried the following

delete []*_board[];
delete []_board;
-------------------------------
for (int i = 0; i < BOARD_HEIGHT; i++)
 delete []*_board[i];
delete []_board;
-------------------------------
for (int i = 0; i < BOARD_HEIGHT; i++)
  delete [](*_board)[i];
delete []_board;
--------------------------------
delete []*_board;
delete []_board;

those also failed, what should i do?
Why not? You can! Your original destructor frees memory normally. The only moment is declaring constructor and destructor as public members.
1
2
3
4
5
6
class ConnectN
{
public:
  ConnectN::ConnectN(int n);
  ConnectN::~ConnectN();
};

You should not mix a pointer with a value it points out. Check the values by e.g.
 
cout << _board[0][0];
Last edited on
*groans at nested new* Obligatory link: http://cplusplus.com/forum/articles/17108/

Anyway your original dtor was correct:

1
2
3
4
5
6
7
8
9
// if allocating like this
_board= new Space*[BOARD_HEIGHT];
for (int i = 0; i < BOARD_HEIGHT; i++)
  _board[i] = new Space[BOARD_WIDTH];

// then you deallocate like this:
for (int i = 0; i < BOARD_HEIGHT; i++)
  delete[] _board[i];
delete[] _board;


The error box that's popping up tells me you have heap corruption.

That is... somewhere in your program you're stepping out of bounds of your array and writing to somewhere you shouldn't be. It likely doesn't have anything to do with your destructor.
closed account (1yR4jE8b)
This is how you delete a dynamically allocated 2D array
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

int main()
{
	//to create a 2d array dynamically
	int** twoDimArray;
	const int SIZE = 10;
	twoDimArray = new int*[SIZE];
	for(int i = 0; i < SIZE; ++i)
	{
		twoDimArray[i] = new int[SIZE];	//	twoDimArray is an int** so twoDimArray[i] is an int*
	}
	
	//to destroy a 2d array
	for(int i = 0; i < SIZE; ++i)
	{
		delete[] twoDimArray[i];
	}
	delete[] twoDimArray;
	
	return 0;
}


Generally You Want to avoid having multidimensional arrays, especially with pointers. I'd go as far
as to say that 2d arrays are EVIL. Generally you want to have a implement a 2d array as a 1D array
and use simple pointer arithmetic to access data.
Generally you want to stay a 1-Star Programmer as much as possible, I get annoyed with 2-Stars and I've
even seen three stars.
1-Star programmer, uses at most int*
2-Star programmer, uses int**
3-Star programmer, int***....I think you get it.


This is how I typically deal with needing to have a 'multi-demensional' data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

template <class T> const T& get(T* array, int desiredRow, int desiredCol, int colSize);

int betterMain()
{
	//to create a 2D array dynamically
	const int ROWS = 10;
	const int COLS = 10;
	int* twoDimArray = new int[ROWS * COLS];
	
	//to access an element of a given row and column of an 1d 2dArray
	int value = twoDimArray[desiredRow * COLS + desiredCol];	//You may find it easier to write the offset calculation as an inline function
        
        //OR
     
	int value = get(twoDimArray, desiredRow, desiredCol, COLS); //function is below
	
	//to delete the array
	delete[] twoDimArray; //that's it, no loops required.
}

template <class T>
inline const T& get(T* array, int desiredRow, int desiredCol, int colSize)
{
	return array[desiredRow * colSize + desiredCol];
}
Last edited on
This is how I typically deal with needing to have a 'multi-demensional' data.


Why not just put it in a class?

IMO, anytime you have dynamically allocated memory, you should try to keep it in a reasonably small class where the ctors/dtors handle all of the allocation/clean up.

*copies his example from the thread he just linked to*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
template <typename T>
class Array2D
{
public:
  // constructor
  Array2D(unsigned wd,unsigned ht)
    : nWd(wd), nHt(ht), pAr(0)
  {
    if(wd > 0 && ht > 0)
      pAr = new T[wd * ht];
  }

  // destructor
  ~Array2D()
  {
    delete[] pAr;
  }

  // indexing (parenthesis operator)
  //  two of them (for const correctness)

  const T& operator () (unsigned x,unsigned y) const
  {  return pAr[ y*nWd + x ];   }

  T& operator () (unsigned x,unsigned y)
  {  return pAr[ y*nWd + x ];   }

  // get dims
  unsigned GetWd() const { return nWd; }
  unsigned GetHt() const { return nHt; }


  // private data members
private:
  unsigned nWd;
  unsigned nHt;
  T*       pAr;

  // to prevent unwanted copying:
  Array2D(const Array2D<T>&);
  Array2D& operator = (const Array2D<T>&);
};


Now it's as easy as:

1
2
3
4
5
Array2D<int> foo(WIDTH,HEIGHT);

int bar = foo( x, y );

foo( x, y ) = bar;
closed account (1yR4jE8b)
Well, yes, I typically DO do it with classes. But for the sake of simplicity, I just showed how do it without needing a class because you need to know how to do it like I showed before you start encapsulating it.
Last edited on
Yes i know it is EVIL
But it is the fixed method to use Space ** in my assignment

About stepping out of bounds, the error did not occur when i ignore the destructor.
would it be possible to have stepping out of bounds in my destructor.
It has nothing to do with your destructor.

You're stepping out of bounds somewhere and it's corrupting memory.

When you free the memory (in your destructor), the corrupted memory is being read and misinterpretted, causing a crash.

The crash could just as easily come in any other random point in the program... or it might not crash at all, it might just make your program behave strangely/unpredictable.

The solution here is to find out where you're stepping out of bounds and fix it. The problem could be anywhere in your program. It's even possible it has nothing to do with this array -- maybe it's a different array, or another stray pointer or something.

Heap corruption is the worst kind of bug.
Topic archived. No new replies allowed.