C++ deleting array on the heap - c++

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.

Related

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

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 :)

Dynamically allocating memory for changing array size starting with unknown size C++

How do I dynamically allocate an array where the size will be changing because the stuff stored in the array will be read from a file. There are lots of suggestions on using a vector, but I want to know how to do it the array way.
I know for memory allocation it is
int count;
int *n = new int[count];
Say the variable count is going to increment in a loop. How would I change the size of the array?
Also, what if we did it using malloc?
Don't try to make the array allocation exactly follow the continual changing size requirements of what you are going to store. Consider using the traditional 2*N multiple. When array is full, reallocate by growing by 2*N (allocate a new array twice as large), and copy items over. This amortizes the reallocation cost logarithmically.
Keep in mind that this logic you are setting out to implement with low level arrays is exactly why vector exists. You are not likely to implement your own as efficiently, or as bug free.
But if you are set on it, keep count a multiple of 2, starting with something realistic (or the nearest multiple of 2 rounded up)
You may keep two pointers, p and q(placeholder), when count changes, you need to do a fresh allocation for p, before that earlier allocations need to be deallocated, even before that the contents of earlier p should be transferred to new p as well.
int count, oldcount;
int *p = NULL;
int *q;
p = new int[count];
oldcount = count;
when you need to re-allocate:
q = new int[count];
memcpy(q, p, oldcount * sizeof(int)); // OR for (int i = 0; i < oldcount; i++) q[i] = p[i];
delete [] p;
p = q;
oldcount = count; // for use later
If you use malloc, calloc then you need to use as number of bytes to pass in malloc. but not needed with new and delete operators in C++
How would I change the size of the array?
Using new: You can't. The size of an object (here, an array object) can't change at runtime.
You would have to create a new array with the appropriate size, copy all elements from the old into the new array and destroy the old one.
To avoid many reallocations you should always allocate more than you need. Keep track of the size (the amount of elements currently in use) and the capacity (the actual size of the allocated array). Once you want to increase the size, check whether there is still some memory left (size<capacity) and use that if possible; otherwise, apply the aforementioned method.
And that's exactly what vector does for you: But with RAII and all the convenience possible.

Delete a pointer array without deleting the pointed objects in memory?

I would like to know if there is a way to delete a pointer array without touching the pointed objects in memory.
I'm writing a restriction routine for a HashSet I implemented a couple of days ago, so when the hash table is full it gets replaced by another double sized table. I'm representing the hash table using an array of pointers to an object (User), and the array itself is declared dynamically in my HashSet class, so it can be deleted after copying all its content to the new table using a hash function.
So basically I need to:
Declare another table with a size that equals the double of the original array size.
Copy every pointer to User objects from my original array to the new one applying my hash function (it gets the User object from memory and it calculates the index using a string that represents the user's name).
After inserting all the pointers from the original array to the new one, I will have to free the allocated memory for the original array and replace the pointer in my HashSet class (member private userContainer) with the location of the new one (array).
The problem is that if I use delete[] userContainer to free the allocated memory for it, it will also delete every object in memory so the newly created replacement array will point to freed positions in memory!
What you describe does not sound right.
Let's say you have a class A and you create an array of As with:
A** array1 = new A*[32];
Then fill it:
for(int i = 0; i < 32; ++i)
array1[i] = new A();
Doing a delete[] array1 does not free the elements of array1.
So this is safe:
A** array1 = new A*[32];
for(int i = 0; i < 32; ++i)
array1[i] = new A();
A** arary2 = new A*[64];
for(i = 0; i < 32; ++i)
array2[i] = array1[i];
delete [] array1;
for(i = 0; i < 32; ++i)
// do something with array2[i]
In general, when you delete an array of pointers, whatever objects the pointers pointed to remain in existence. In fact, this is a potential source of large memory leaks.
But in some sort of reference-counted environment (eg, Objective-C or Qt), when you delete an array OBJECT (vs a simple [] array) then the reference counts are decremented and the objects will be deleted if the count goes to zero.
But if you're restructuring a hash table you'd better have somehow saved the pointer values before you delete the array, or else all the addressed objects will be lost. As you save them you can increment their reference counts (if you do it right).
(It would help to know what language you're dealing with, and what you mean by "array".)
I don't think your problem exists. Here's a baby example to show that there's nothing to worry about:
Foo * brr[10];
{
Foo * arr[10];
// This is not touching the objects!
for (Foo * it = arr; it != arr + 10; ++it) *it = new Foo;
std::copy(arr, arr + 10, brr);
} // no more arr
for (Foo * it = brr; it != brr + 10; ++it) delete *it; // fine
You can copy the pointers around freely as much as you like. Just remember to delete the object to which the pointers point when they're no longer needed.
A perhaps trivial reminder: Pointers don't have destructors; in particular, when a pointer goes out of scope, nothing happens.
Do you know the difference between malloc/free, new/delete and new[]/delete[]?
I figure that you might want to not use new[]/delete[] in your situation, as you don't want destructors to be called I guess?

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[].

How to expand an array dynamically in C++? {like in vector }

Lets say, i have
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
Now I want to add a 6th element to the array. How do I do it?
You have to reallocate the array and copy the data:
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
// realloc
int* temp = new int[6];
std::copy(p, p + 5, temp); // Suggested by comments from Nick and Bojan
delete [] p;
p = temp;
You cannot. You must use a dynamic container, such as an STL vector, for this. Or else you can make another array that is larger, and then copy the data from your first array into it.
The reason is that an array represents a contiguous region in memory. For your example above, let us say that p points to address 0x1000, and the the five ints correspond to twenty bytes, so the array ends at the boundary of 0x1014. The compiler is free to place other variables in the memory starting at 0x1014; for example, int i might occupy 0x1014..0x1018. If you then extended the array so that it occupied four more bytes, what would happen?
If you allocate the initial buffer using malloc you can use realloc to resize the buffer. You shouldn't use realloc to resize a new-ed buffer.
int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);
However, this is a C-ish way to do things. You should consider using vector.
Why don't you look in the sources how vector does that? You can see the implementation of this mechanism right in the folder your C++ include files reside!
Here's what it does on gcc 4.3.2:
Allocate a new contiguous chunk of memory with use of the vector's allocator (you remember that vector is vector<Type, Allocator = new_allocator>?). The default allocator calls operator new() (not just new!) to allocate this chunk, letting himself thereby not to mess with new[]/delete[] stuff;
Copy the contents of the existing array to the newly allocated one;
Dispose previously aligned chunk with the allocator; the default one uses operator delete().
(Note, that if you're going to write your own vector, your size should increase "M times", not "by fixed amount". This will let you achieve amortized constant time. For example, if, upon each excession of the size limit, your vector grows twice, each element will be copied on average once.)
Same as others are saying, but if you're resizing the array often, one strategy is to resize the array each time by doubling the size. There's an expense to constantly creating new and destroying old, so the doubling theory tries to mitigate this problem by ensuring that there's sufficient room for future elements as well.