Jame
Jame

Reputation: 3854

How to delete completely 2D pointer array

I have a 2D pointer matrix in C++ such as,

typedef unsigned char  U8;
typedef unsigned int   U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
    A[i] = new U8[m_L];
}

After setting value in A0, I will write a function which decide delete or not delete M-2 rows in A, depends on the random number is 0 or 1

void delete_or_not(U8** A,int M) 
{
  if (rand_num==1){
     for (U32 index = M-2; index < M; ++index){
        delete[] A[index];
     }
  }
}

Now, in main function (which contains A memory allocation), I want to free/delete the memory which allocated for A. I can use the code

//free A matrix
for (U32 i = 0; i < M; ++i)
{
    if (i < m_L)
    {
      delete[] A[i];
      A[i] = NULL;
    }
}
delete[] A;
A = NULL;

My problem is that, I don't know that A is delete (M-2) rows or not. Hence, above code does clearly delete all memory, if my random number is 0. That means, above code only delete correct memory if M-2 rows is deleted in the delete_or_not function. How can delete the A matrix perfectly. Thanks

Finaly, my full code is

typedef unsigned char  U8;
typedef unsigned int   U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
    A[i] = new U8[m_L];
}
delete_or_not(A,M);
//free A matrix 
//Way 1: will miss M-2 row if delete_or_not function did not delete 2 rows.
// It only correct if rand_num=1
for (U32 i = 0; i < M; ++i)
{
    if (i < m_L)
    {
      delete[] A[i];
      A[i] = NULL;
    }
}
delete[] A;
A = NULL;

//Way 2- It will correct if the size of A is M by M

for (U32 i = 0; i < M; ++i)
{
      delete[] A[i];
      A[i] = NULL;
}
delete[] A;
A = NULL;

Upvotes: 3

Views: 122

Answers (2)

4386427
4386427

Reputation: 44274

In void delete_or_notyou shall set deleted elements to NULL as already proposed by another answer by Amit.

Then Way 2 of your posted code is correct in both cases.

Calling delete on a NULL is perfectly legal and doesn't hurt at all.

Way 1 is not working and should be removed.

In summary:

void delete_or_not(U8** A,int M) 
{
  if (rand_num==1){
     for (U32 index = M-2; index < M; ++index){
        delete[] A[index];
        A[index] = NULL;    // Add this to your code
     }
  }
} 


// In main somewhere...

// free A
for (U32 i = 0; i < M; ++i)
{
      delete[] A[i];   // Not a problem if the element has already been deleted
                       // because the pointer will be NULL and calling
                       // delete with NULL is OK (and changes nothing)
      A[i] = NULL;
}
delete[] A;
A = NULL;

Upvotes: 1

Amit
Amit

Reputation: 46323

Just set deleted elements to NULL and everything will work fine:

void delete_or_not(U8** A,int M) 
{
  if (rand_num==1){
     for (U32 index = M-2; index < M; ++index){
        delete[] A[index];
        A[index] = NULL;
     }
  }
}

Also, this is not very useful:

for (U32 i = 0; i < M; ++i)
{
    if (i < m_L)
    {
      delete[] A[i];
      A[i] = NULL;
    }
}

There's no point advancing i from 0 to M if you then only "do work" when i is smaller then m_L.


But really, in C++ you should probably use std::vector<std::vector<U8>> instead and simply erase or pop_back to get rid of "rows".

Upvotes: 4

Related Questions