When should I use delete? (Consequences of not deleting after a dynamically created 2d array) - c++

I am new to dynamic allocation and pointers. I will try to fill out a 2D dynamic array from a file and then apply a maze-solving algorithm (wall follower)on it.
Assuming I create a dynamically allocated 2D array like this:
int** board;
board = new int* [rowsize];
for(int row = 0; row < rowsize; row++)
{
board[row] = new int[colsize];
}
If I know that I won't be using this pointer for another variable, can I get away with not using delete for board ? If not what could potentially go wrong (If you are familiar with the wall follower algorithm) ? Also how do I delete a pointer to a pointer, would delete board be sufficient?

can I get away with not using delete for board?
Yes, but not for very long: repeated failure to delete arrays that your program allocates is a memory leak that eventually runs your process out of memory.
how do I delete a pointer to a pointer, would delete board be sufficient?
No, you will need to delete each pointer that you allocated and stored inside board:
for(int row = 0; row < rowsize; row++) {
delete[] board[row];
}
delete[] board;
Note square brackets after delete to indicate that you deleting an array, they are very important.
Allocating an deallocating memory for a rectangular matrix is a solved problem in C++ library. Switch to using a vector of vectors to avoid dynamic resource allocations:
std::vector<std::vector<int>> board(rowsize, std::vector<int>(colsize, 0));

If you don't delete the arrays you allocated they will continue to consume memory until the program is terminated. This might not technically be wrong, but it is wasteful.
With regard to deleting the board - no, it is not enough. You should delete every pointer you allocate with new:
for(int row = 0; row < rowsize; row++)
{
delete[] board[row];
}
delete[] board;

What you need to delete is the memory you allocated with new. That means that you don't deallocate the pointer itself, but the heap's memory it is pointing at.
So, you only need to do delete[] board. This will free up the int* array. It is not strictly necessary to use [] in this case, since it is a fundamental type array, but it is good practice to use it always for arrays, so you won't mess up when it's not like that.
Calling delete[] on an array will call the destructors of all objects inside the array itself, as well as freeing up the array. It is not necessary however for fundamental types.
Also note that you don't need to free the int** board. The pointer are variables like any other with some special capability, but they are allocated in the stack just like any other when you declare them like that.
Hope it helps :)

Related

Trying to deallocate a dynamic array of std::forward_list pointers (C++)

I'm trying to deallocate a dynamically allocated array of pointers to forward lists that was created with something like:
deck = new forward_list<T>*[numDecks];
for (int i = 0; i < numDecks; i++) {
deck[i] = new forward_list<T>;
}
numberOfDecks = numDecks;
I tried to iterate and delete the decks like this:
for (int i = 0; i < numDecks; i++) {
delete[] deck[i];
numberofDecks--;
}
delete[] deck;
But I got a read access violation. In fact, even if I just write:
delete[] deck[0];
I still get a read access violation. I've been playing around with this for quite some time and haven't been able to get it to work. I'm attaching a screenshot of the error (it appears in the forward_list file.
Thank you.
delete[] is for deleteing something that was allocated via new []. When you allocated something via new you need to delete it via delete.
There is no apparent reason for any manual dynamic allocations in your code. The std::forward_list already manages the memory of its elements. Storing pointers in the list has no advantage unless you need a level of indirection for some reason. And if you need it you should use smart pointers not raw ones. Also allocating the std::forward_list itself dynamically is most likely not needed (and again: use smart pointer if you do).
Your code has undefined behavior, as you are creating the std::forward_list objects using new but then destroying them with delete[] instead of delete. You need to change this:
delete[] deck[i];
To this:
delete deck[i];
new/delete are for single objects, and new[]/delete[] are for arrays. They must be matched up properly.
A better option is to use std::vector<std::forward_list> instead of std::forward_list*[], and let the vector handle the memory for you.

C++ deleting array on the heap

I'm having difficulty finding an answer on how to specifically perform this operation properly.
I'd like to better understand different ways to delete new memory allocated on the heap, especially in the instance of a two-D array.
For my example:
I have an array of size 5 on the stack consisting of int pointers (int *d[5]).
I initialize each of these int pointers in a loop to create and point to an int array of size 8 on the heap (d[i] = new int[8]).
I have now essentially created a two-D array (d[j][k]).
My question is what is the syntax for deleting only the individual arrays (int[8]) on the heap?
I currently have it as this, but when debugging it appears the arrays are not deallocated after it is performed...
for(int i = 0; i < 5; ++i)
delete d[i];
Should it be "delete [] d[i]" or just "delete [] d" or some other variation? Also, is there a way to delete the individual elements of the int[8] arrays? If anyone could concisely explain the syntax and their differences that would be super helpful. Thank you!
If you allocated arrays via d[i] = new int[8], then you must delete them via delete[] d[i]. There's no way to deallocate individual elements of such an array without deallocating the whole thing.
you mentioned that you are allocating the inner arrays within a loop. which I believe it looks something like this.
int*d[2];
for (int i = 0; i < 2; i++)
{
d[i] = new int[3];
}
Notice that d[2] contains just pointers to the arrays.
so in order to delete this array, you have to iterate through each set of array pointers
and call delete[] d[i];
for (int i = 0; i < 2; i++)
{
delete[] d[i];
}
As an additional note, it would be very advantageous to know how your IDE tries to detect memory corruptions.
for example in the visual studio (In DEBUG mode)
0xCD means Allocated memory via malloc or new but never written by
the application.
0xCC means uninitialised variables.
0XDD means memory has been released with delete or free.
0xFD means fence memory and acts as a guard. used for detecting indexing arrays that go out of bounds.
with that in mind lets see if we can make sense of what the IDE is doing when the above code is executed.
When the d array is declared int*d[2]; the memory layout looks like the following;
notice that d array has two elements but none of those have initial values so they are assigned to the 0xCC
lets see what happens after we do d[i] = new int[3];
notice that d array now has two elements each element contains an int array. the values you see are the address of the pointers to the array we allocated the memory for.
since we know what the addresses are we can look into the memory and see whats happening in there when allocating and deleting the each array.
for example after we allocate our second int array within the for loop, the memory location would look something like this;
notice that all the array element has 0xCD with ending of 0xFD.This would indicate in my IDE that the memory allocated and has a fence guards around it.
lets see what happens when the d[2] is deleted.

Ways to tell if you have successfully released dynamic allocated memory

This is how i allocate dynamic memory for a 2D array
char **twod;
twod=new char*[count];
for (int i = 0; i < count; i++)
{
twod [i] = new char [MAX];
}
This is how i release the memory for a 2D array
for (int i=0; i<count;i++)
{
delete [] twod [i];
}
delete [] twod;
How do i know i have successfully released everything and there is no memory leak???
Ways to tell if you have successfully released dynamic allocated memory
Run the code in valgrind or any such memory leak detection tool.
If you want you could also overload the new and delete operators for your class and do the bookeeping yourself but that it too much effort so you are much better off setting with a memory leak detection tool.
Ofcourse I consider the example only an sample example and not the code one will usually go for because:
You are better off avoiding dynamic allocations, use automatic variables instead.
If you must then use smart pointers with RAII and not raw pointers.

Proper way to delete an array of pointers

I have an array of pointers (that I created by calling new ptr*[size]). All of these pointers point to an object that was also put on the heap.
What is the proper way to delete the array and all new'd ptr's?
This is what I do now:
for (int i = 0; i < size; i++) delete array[i];
delete[] array; // Not sure since this double deletes array[0]
Does this do what I think it should?
Thanks
Every pointer allocated with new gets a corresponding delete. Every pointer allocated with new [] gets a corresponding delete []. That's really all you need to know. Of course, when you have a dynamically allocated array which contains dynamically allocated pointers the deallocation must occur in reverse order.
So it follows that the correct idiom would be...
int main()
{
int **container = new int*[n];
for(int i = 0; i < n; ++i)
container[i] = new int[size];
// ... and to deallocate...
for(int i = 0; i < n; ++i)
delete [] container[i];
delete [] container;
}
And then of course I say "stop doing that" and recommend you use a std::array or std::vector (and the template type would be unique_ptr<int>).
Yes, that does what you think it should. Since you did new for each element, you have to delete each element. And since you did new[] for the entire array, you need to delete[] the entire array.
As #djechlin rightly says in the comments, there's not really enough information to go on, but I'm presuming your prior code is something like this:
int** array = new int*[5];
for (int i = 0; i < 5; i++) {
array[i] = new int;
}
Note that array is not actually an array type. It is a "pointer to pointer to int" and the array of pointers it points to was allocated with new[]. That's why you need to delete[] it.
Yes. First you have to free the object each pointer in the array points to, then you have to free the array itself. In that order. If you reverse the order you'll have no reference to the objects and will leak a lot of memory.
Yes, first you delete each object to which elements of array point, and then you delete array of pointers itself. If you want to check your memory management, you can use tools like valgrind, they will be able to spot most errors.

Why does calling 'delete' in a specific way on a dynamic array not work?

I'm wondering why this code doesn't work:
void KeyValueList::Release()
{
//(m_ppKeyValueList is a dynamic array of pointers to objects on the heap)
if (m_ppKeyValueList) {
for (int i = 0; i < m_iCapacity; ++i) {
if (m_ppKeyValueList[i]) {
delete m_ppKeyValueList[i];
}
}
/*delete[] m_ppKeyValueList;*/
for (int i = 0; i < m_iCapacity; ++i) {
delete (m_ppKeyValueList + i);
}
}
}
Why can't we iterate the dynamic array and delete it in this way?
A dynamic array is more than just a sequence of elements. It contains information about the array size as well. Moreover, there is just one chunk of memory known to the allocator. So just like with any dynamic memory, you can only free what you allocated, not smaller subsets of it.
That's why the language requires that you only invoke delete[] on a pointer obtained from a new[] expression, and that that is the only way to deallocate that memory.
Simple answer: because the language specifications say that you do that with a delete[].
Better answer: because after all for the heap manager the array pointed by m_ppKeyValueList is a single large allocation, not m_iCapacity consecutive small allocations, so you just have to tell it where the allocated block begins and it will deallocate it as a whole (after calling the single destructors if needed); if it kept each element as a single separated allocation into the allocated block lists it would be a stupid waste of resources (and if it used a bitmap for this it probably wouldn't have enough granularity to support this silly allocation scheme).
Because new int[5] allocates one contiguous block big enough to hold 5 ints. new int 5 times allocates 5 small blocks, each big enough to hold a single int. The number of deallocations must equal the number of allocations.
Case 1: m_ppKeyValueList is "a dynamic array of pointers to objects on the heap"
In this case you do need to delete m_ppKeyValueList piece by piece. If this is what you meant, your declaration will be of the form SomeType ** m_ppKeyValueList; Your allocation and deallocation should like
Allocation:
m_ppKeyValueList = new SomeType*[m_iCapacity];
for (int i = 0; i < m_iCapacity; ++i) {
m_ppKeyValueList[ii] = new SomeType;
}
Deallocation:
for (int i = 0; i < m_iCapacity; ++i) {
delete m_ppKeyValueList[ii];
}
delete[] m_ppKeyValueList;
However, that your code fails suggests that you do not have "a dynamic array of pointers to objects on the heap."
Case 2: m_ppKeyValueList is a dynamic array of objects on the heap
Here your declaration will be of the form SomeType * m_ppKeyValueList; Instead of allocating this piece by piece your allocation and deallocation take on a much simpler form:
Allocation:
m_ppKeyValueList = new SomeType[m_iCapacity];
Deallocation:
delete[] m_ppKeyValueList;
Bottom line:
Your allocations and deallocations need to match one another in number and in form. If you allocate something with new you need to destroy it with delete. If you allocate it with new[] you need to destroy it with delete[].