0

actually the size of a multidimensional array I don’t know, it can be such a

arr[i][k][j]; 

or such a

arr[i][k][j][l];

or such a

arr[i];

I recognize this after starting, but I also need to delete or clear the array completely

I tried to do it like this

memset(&arr[i][k], 0, sizeof arr[i][k]);

and tried to do so

delete arr[i][k];

But the array is still not deleted, maybe there is a ready-made library that allows me to do this, please help.

int main() 
{ 
    int M ;
    int N ; 
    int i, j;
    int** matrix;
    cin >> M;
    cin >> N;

    matrix = new int*[M]; 
    for ( i = 0; i < M; i++) 
        matrix[i] = new int[N];

    for ( i = 0; i < M; i++) 
        for ( j = 0; j < N; j++) 
        { 
            cout << "Inter element " << "[" << i << "][" << j << "]  "; 
            cin >> matrix[i][j]; 
        }

        cout << endl;
        for ( i = 0; i < M; i++) 
            for ( j = 0; j < N; j++) 
            { 
                cout << matrix[i][j]; 
            } 
            cout << endl;
}
loli
  • 17
  • 6
  • 3
    What do you mean by "removing" and "deleting"? Do you want to zero all the elements? – Evg Dec 11 '19 at 20:59
  • 2
    also what do you mean with "the array is still not deleted". The thing is there is no way to see that, because once deleted you are not allowed to access it anymore – 463035818_is_not_an_ai Dec 11 '19 at 21:00
  • 3
    Please provide a [mcve] – 463035818_is_not_an_ai Dec 11 '19 at 21:00
  • There is no completely clean and delete from memory, during the cycle the memory is full if the array is not completely removed and the program crashes. – loli Dec 11 '19 at 21:01
  • `delete` (i.e. freeing memory) and overwriting with zero (`memset`) are too completely independent things to do. If you want to free the memory, you first need to show how you allocated it. – walnut Dec 11 '19 at 21:02
  • Multi dimensional arrays get huge, fast. – user4581301 Dec 11 '19 at 21:02
  • 1
    how do you do that? It is unclear what you are talking about. Please show code – 463035818_is_not_an_ai Dec 11 '19 at 21:02
  • I threw off an example, the point is that the array can be any, depending on what I write, and I would like to just delete it right away if the function turns off. – loli Dec 11 '19 at 21:13
  • in the code you posted you are not calling any `delete`. With "the array is still not deleted". do you mean that you can still access the array elements after calling `delete`? – 463035818_is_not_an_ai Dec 11 '19 at 21:13
  • for every `new` you need a `delete`... – 463035818_is_not_an_ai Dec 11 '19 at 21:14
  • 1
    @loli You delete it the same way you allocated it. Just with `delete[]` instead of `new[]`. – Algirdas Preidžius Dec 11 '19 at 21:14
  • You cannot completely delete the allocated memory without knowing exactly how you allocated it. There must be one `delete[]` executed (not `delete`!) for each `new[]` executed. I suggest you stop using `new`/`delete` all together and use `std::vector` instead, which is the proper way to handle arrays of dynamic size in C++. Using raw `new`/`delete` outside of a class managing one specific `new` allocation is considered bad style (you can see why) and is not exception-safe. – walnut Dec 11 '19 at 21:16
  • you can try [boost::multi_array](https://www.boost.org/doc/libs/1_70_0/libs/multi_array/doc/user.html) – Thomas Dec 11 '19 at 21:17
  • and I can do the removal once so as not to cause constantly delete[]? – loli Dec 11 '19 at 21:17
  • You need one delete[] for each and every new[]. You could make a matrix class that contains a matrix class of a dimension one smaller - then you would need just one new[] in the constructor and one delete[] in the destructor. Or you could use the built in vector class like was suggested before. – Jerry Jeremiah Dec 11 '19 at 21:19
  • I realized thanks to everyone. – loli Dec 11 '19 at 21:26
  • Side note: this sort of multi-dimensional array can be quite slow because there is no spatial connection between the many arrays that make it up. If the array is rectangular (all of the columns are the same size) you are often better off allocating one big array and faking the second dimension by performing the indexing yourself. [Here's a good example](https://stackoverflow.com/a/2076668/4581301) using a `std::vector` that you can use as a basis for your own array. – user4581301 Dec 11 '19 at 22:03
  • [Here is an incomplete implementation](https://isocpp.org/wiki/faq/operator-overloading#matrix-subscript-op) of the same thing without `std::vector`. Pay special attention to the copy constructor and assignment operator that are [required to make sure the allocated array is properly handled](https://en.cppreference.com/w/cpp/language/rule_of_three). Sadly they are not implemented in this example. `std::vector` looks after the copying for you, allowing other objects using `std::vector` to observe the Rule of Zero (see preceding link). – user4581301 Dec 11 '19 at 22:06

1 Answers1

1

When you create an array with new SomeType[M] you must use delete [] to free the memory allocated to the array.

In the case of 2D arrays as you have written, you create an array of pointers first. Let's call this the "outer array". Then for each element in the outer array you create another array again with new SomeType[N]. The return of new SomeType[N] is a pointer, which will point to the corresponding "inner array".

In order to free all the memory in your "2D array" you need to first call delete [] for each inner array and only after that you call delete [] for the outer array. Not doing any of these will result in a memory leak.

In you example you don't have any delete command and thus we know for sure that there is a memory leak. Let's pretend we don't know this and check with valgrind. If we ran the executable with valgrind passing 2 and 3 as the inputs for the size, then valgrind returns something like

==194743== 
==194743== HEAP SUMMARY:
==194743==     in use at exit: 40 bytes in 3 blocks
==194743==   total heap usage: 6 allocs, 3 frees, 74,792 bytes allocated
==194743== 
==194743== LEAK SUMMARY:
==194743==    definitely lost: 16 bytes in 1 blocks
==194743==    indirectly lost: 24 bytes in 2 blocks
==194743==      possibly lost: 0 bytes in 0 blocks
==194743==    still reachable: 0 bytes in 0 blocks
==194743==         suppressed: 0 bytes in 0 blocks
==194743== Rerun with --leak-check=full to see details of leaked memory
==194743== 
==194743== For lists of detected and suppressed errors, rerun with: -s
==194743== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

The leak summary from valgrind clearly tells us that some memory was not properly freed. Now, add the following code to the end of your main function to properly free all that memory

// Free all the inner arrays. Notice that we call `delete []` passing the
// pointer of an inner array
for ( i = 0; i < M; i++) {
    delete [] matrix[i];
}

// Delete the outer array. Notice that now we pass the pointer of the outer array
delete [] matrix;

If we ran this with valgrind again we get something like

==197046== 
==197046== HEAP SUMMARY:
==197046==     in use at exit: 0 bytes in 0 blocks
==197046==   total heap usage: 6 allocs, 6 frees, 74,792 bytes allocated
==197046== 
==197046== All heap blocks were freed -- no leaks are possible
==197046== 
==197046== For lists of detected and suppressed errors, rerun with: -s
==197046== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Valgrind is now telling us that we have indeed freed all the memory we have dynamic allocated.

All heap blocks were freed -- no leaks are possible

darcamo
  • 3,294
  • 1
  • 16
  • 27