How to delete completely 2D pointer array - c++

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;

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".

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;

Related

Array resizing. Why cannot I resize the array second time? _CrtIsValidHeapPointer(PUserData)

I want to resize the array multiple times.It does that the first time but after that, it throws me an error. When I do it the second time, I get an error _CrtIsValidHeapPointer(PUserData). Can someone help me out?
int main()
{
int size = 8;
int *arr = new int[size];
arr[1] = 25;
arr[2] = 30;
int count = 0; //to check size
for (int i = 0; i < size; i++)
{
count = count + 1;
}
cout << count << endl;
resize(arr, size);
int new_count = 0; //to confirm size change
for (int i = 0; i < size; i++)
{
new_count = new_count + 1;
}
cout << new_count << endl;
resize(arr, size);
int new_count2 = 0; //to confirm size change
for (int i = 0; i < size; i++)
{
new_count2 = new_count2 + 1;
}
cout << new_count2 << endl;
return 0;
}
void resize(int *a,int &size)
{
int newsize = 2 * size;
int *arr_new = new int[newsize];
for (int i = 0; i < size; i++) //copy everything
{
arr_new[i] = a[i];
}
size = newsize; //new value of size
delete [] a;
a = arr_new; //Pointer pointing to new array
delete arr_new;
}
There are two problems with this code:
void resize(int *a,int &size)
{
[...]
delete [] a;
a = arr_new; //Pointer pointing to new array
delete arr_new; // huh????
}
The first problem is that you are calling the delete operator twice; the first call deletes the old array (which makes sense), but then you attempt to delete the newly allocated array also (via delete arr_new). How is the caller going to able to use the newly allocated array when resize() has already deleted it before it returned?
The second problem is that you set a to point to the new array (i.e. a = arr_new;) but a is a local function-argument that goes out of scope when resize() returns, so the calling code will never see its new value. I think you want this instead:
void resize(int * & a,int &size) // note the & before a!
Passing a by reference will allow the caller to see a's new value after resize() returns.

Class deconstructor and pointers

We were writing a code in our university (learning about Object Oriented Program). We wrote this class and the issue is that, as per my understanding and our teacher the program should crash in the following condition, but in my case it doesn't.
The thing is this line is the culprit
DynamicArray d, f;
f = d;
according to him(rest of the code is attached), since when main ends, deconstructor deletes f and then goes for d, but since pointer was pointing to same mem location in both cases, now it should give error when it tries to delete it, since there is nothing there....but my compiler runs the code perfectly. I am using gcc compiler. Denconstructor at the end of class, rest is to fill dynamic array.
#include <iostream>
#include <ctime>
class DynamicArray{
private:
int *arr;
int size, cap; //cap is the physical size, size is number of elements
public:
DynamicArray(){
arr = nullptr;
size = cap = 0;
}
DynamicArray(int i){
cap = i;
size = 0;
arr = new int[cap];
}
void pushback(int j){
if(cap == 0){
arr = new int[cap];
arr[0] = j;
size++;
cap++;
}
else if(size < cap){
arr[size] = j;
size++;
}
else if(size == cap){
int *arr2 = new int[cap * 2];
int i;
cap *= 2;
for(i = 0; i < size; i++){
arr2[i] = arr[i];
}
arr2[i++] = j;
delete[] arr;
arr = arr2;
}
}
void print(){
for(int i = 0; i < size; i++)
std::cout << arr[i] << " ";
}
~DynamicArray(){
if(arr != nullptr)
delete[] arr;
}
};
int main(){
DynamicArray d, f;
srand(time(nullptr));
int n = rand() % 5;
for(int i = 0; i < n; i++){
d.pushback(rand() % 10);
}
f = d;
f.print();
std::cout << std::endl;
d.print();
return 0;
}
Your code causes so-called "undefined behaviour". Basically, that means anything can happen, including that nothing happens or that whatever happens isn't easily observable. For a more precise definition of "undefined behaviour", you'd have to check e.g. the C++ standard, but there are also many discussions concerning this term here.
Try running your code using e.g. valgrind, it will tell you that your code is broken.

C++ Delete array inside 2D vector

Unfortunately I have to use arrays in order to use another function I have copied. Changing this function to work with vectors would be way over my head. So I wrote a function declaring me bunch of arrays in heap to be stored inside a vector.
I now have trouble freeing up that memory at the end.
void _get_X_Y_arrays(std::vector<std::vector<float> > *voronoi, std::vector<std::vector<int*> > *rtrn)
{
int numberPolygons = voronoi->size();
for (int i = 0; i < numberPolygons; i++)
{
int *x_heap = new int[((*voronoi)[i].size()) / 2];
int *y_heap = new int[((*voronoi)[i].size()) / 2];
std::vector<int> x(((*voronoi)[i].size()) / 2);
std::vector<int> y(((*voronoi)[i].size()) / 2);
unsigned j = 0;
int count = 0;
for (; j < (*voronoi)[i].size(); j += 2, count++)
{
x[count] = (int)(*voronoi)[i][j];
y[count] = (int)(*voronoi)[i][j + 1];
}
std::copy(x.begin(), x.end(), &x_heap[0]);
std::copy(y.begin(), y.end(), &y_heap[0]);
(*rtrn)[i].push_back(x_heap);
(*rtrn)[i].push_back(y_heap);
}
}
The function works well and everything acts like intended. I wrote another function to free up that memory at the end when it's no longer needed:
void _cleanup(std::vector<std::vector<int*> > *rtrn)
{
for (unsigned i = 0; i < rtrn->size(); i++)
{
for (unsigned j = 0; j < (*rtrn)[i].size(); j++)
{
delete[] rtrn[i][j][0];
delete[] rtrn[i][j][1];
}
}
}
Unfortunately this causes the program to crash. I don't really know where the error is. It feels like there might be an vector out of scope ..?
Just by looking at it and playing with it I'm not able to solve this. What am I doing wrong?
I think you have 3 dimensions array [nbpolygons][2][nbpoints]
Your code :
delete[] rtrn[i][j][0]; // delete rtrn[i][j] index 0
delete[] rtrn[i][j][1]; // delete rtrn[i][j] (the same array) index 1
// => crash
rtrn[i].size() always egal 2
Do :
void _cleanup(std::vector<std::vector<int*> >& rtrn)
{
for (unsigned i = 0; i < rtrn.size(); i++)
{
for (unsigned j = 0; j < rtrn[i].size(); j++)
{
delete[] rtrn[i][j];
}
}
}
or
void _cleanup(std::vector<std::vector<int*> >& rtrn)
{
for (unsigned i = 0; i < rtrn.size(); i++)
{
delete[] rtrn[i][0];
delete[] rtrn[i][1];
}
}

Insert element in array

void insert(int*arr, int element,int index)
{
if (index < SIZE)
{
arr[index] = element;
}
else
{
int* new_array = new int[SIZE + 1];
int i = 0;
for (i = 0; i < SIZE; i++)
{
new_array[i] = arr[i];
}
new_array[i] = element;
SIZE++;
printArray(new_array);
}
}
I have made an insert function in C++ that will insert values at specific indices of the array.After index gets increased I made a new array and copied values from the smaller array into it.
Problem is that printArray function which is just looping to print the array does well when it is called inside the insert function otherwise when I called printArray from the main last value of the array was garbage why is that?
You need to delete the old array and return the new array in its place, e.g.:
void insert(int* &arr, int element, int index) // <<< make `arr` a reference so that we can modify it
{
if (index < SIZE)
{
arr[index] = element;
}
else
{
int* new_array = new int[SIZE + 1];
for (int i = 0; i < SIZE; i++)
{
new_array[i] = arr[i];
}
new_array[SIZE] = element;
SIZE++; // <<< NB: using a global for this is not a great idea!
delete [] arr; // <<< delete old `arr`
arr = new_array; // <<< replace it with `new_array`
}
}
LIVE DEMO
Note that all this explicit low level management of your array goes away if you start using proper C++ idioms, such as std::vector<int> instead of C-style int * arrays.

allocating extra memory for a container class

Hey there, I'm writing a template container class and for the past few hours have been trying to allocate new memory for extra data that comes into the container (...hit a brick wall..:| )
template <typename T>
void Container<T>::insert(T item, int index){
if ( index < 0){
cout<<"Invalid location to insert " << index << endl;
return;
}
if (index < sizeC){
//copying original array so that when an item is
//placed in the middleeverything else is shifted forward
T *arryCpy = 0;
int tmpSize = 0;
tmpSize = size();
arryCpy = new T[tmpSize];
int i = 0, j = 0;
for ( i = 0; i < tmpSize; i++){
for ( j = index; j < tmpSize; j++){
arryCpy[i] = elements[j];
}
}
//overwriting and placing item and location index
elements[index] = item;
//copying back everything else after the location at index
int k = 0, l = 0;
for ( k =(index+1), l=0; k < sizeC || l < (sizeC-index); k++,l++){
elements[k] = arryCpy[l];
}
delete[] arryCpy;
arryCpy = 0;
}
//seeing if the location is more than the current capacity
//and hence allocating more memory
if (index+1 > capacityC){
int new_capacity = 0;
int current_size = size();
new_capacity = ((index+1)-capacityC)+capacityC;
//variable for new capacity
T *tmparry2 = 0;
tmparry2 = new T[new_capacity];
int n = 0;
for (n = 0; n < current_size;n++){
tmparry2[n] = elements[n];
}
delete[] elements;
elements = 0;
//copying back what we had before
elements = new T[new_capacity];
int m = 0;
for (m = 0; m < current_size; m++){
elements[m] = tmparry2[m];
}
//placing item
elements[index] = item;
}
else{
elements[index] = item;
}
//increasing the current count
sizeC++;
my testing condition is
Container cnt4(3);
and as soon as i hit the fourth element (when I use for egsomething.insert("random",3);) it crashes and the above doesnt work. where have I gone wrong?
Several things don't make too much sense to me:
if (index+1 > capacityC){
shouldn't that be:
if (index >= capacityC){
Also, when you grow the array I don't see why you are doing two lots of copying. shouldn't:
delete[] elements;
elements = 0;
be:
delete[] elements;
elements = tmparray2;
Note that new T[n] is probably not what you actually want in a container of T, because this already creates n objects of type T. What you really want is to reserve memory, and then at some later point in time construct objects of type T in that memory.
T* data = static_cast<T*>(operator new[](n * sizeof(T)); // allocate memory
// ...
new(&data[size]) T(arguments); // construct T object in-place
++size;
In order to destruct the container, you have to reverse the process: destruct the objects one by one and then release the memory.
while (size) data[--size].~T(); // destruct T object in-place
operator delete[](data); // release memory