C++ freeing memory allocation of array with sub arrays - c++

Theoretically, is it enough if I only delete arrays and results but don't delete sub_array inside of arrays in the following code snippet, before return 0; or do I have to first delete all the sub_array before I can safely delete arrays and results.
int main() {
int subarrays, queries;
cin >> subarrays >> queries;
int** arrays = new int* [subarrays]();
int* results = new int[queries];
for (int i = 0; i < subarrays; i++) {
int length;
cin >> length;
int* sub_array = new int[length];
for (int j = 0; j < length; j++) {
int element;
cin >> element;
sub_array[j] = element;
}
arrays[i] = sub_array;
}
for (int i = 0; i < queries; i++) {
int query_from, arr_index;
cin >> query_from >> arr_index;
results[i] = arrays[query_from][arr_index];
}
for (int i = 0; i < queries; i++) {
cout << results[i] << endl;
}
return 0;
}

You shouldn't delete sub_array because the buffer it points to is stored in arrays[n]. As the only way you could delete sub_array is inside the block scope it was declared (which is the for loop), if you do delete it then arrays[n] will be a dangling pointer (a pointer that points to a freed or invalid memory block) and dangling pointers are evil.
What you should do about arrays and sub_array is when they are not needed anymore, you first iterate through all elements of arrays, deleting each one of them and after this, delete arrays itself. Something like:
// when you are done with them
for(auto i = 0; i < subarrays; i++)
{
delete[] arrays[i];
}
delete[] arrays;
As a side-note you should consider using smart pointers in this code.

Yes, you have to first delete all the sub_array before I can safely delete arrays and results to prevent memory leak.
You can employ a loop to go through the sub-arrays in the array.

Related

The program crashes sometimes and works perfectly fine sometimes. A variable array is declared and its size changes 2 times in the program

The program crashes sometimes and works perfectly fine sometimes. A variable array is declared and its size changes 2 times in the program. I am using visual studio. It is in c++.
This is the code in c++:
int sz; //size of array
std::cin >> sz; //getting size
int* arr = new int[sz]; //declaring variable array.
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning values to all members of array
std::cout << arr[i] << std::endl; //printing the array
}
std::cin >> sz; //size changes again
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning new values
std::cout << arr[i] << std::endl; //printing the array
}
On this line:
std::cin >> sz; //size changes again
The comment is not really correct. The variable representing the size is changed, but the array arr is not changed. So indexing into any position greater than or equal to the old size will invoke undefined behavior. This means the program may work sometimes, and not others.
To resize the arr array, after the above line you need to do:
delete [] arr;
arr = new int[sz];
If you want to resize arr you must delete the old one and allocate a new one
delete[] arr;
arr = new int [sz];
If you allocate a vector with new you should delete it after you no longer need it, and don't reuse it arbitrarily so your code would be better as:
int sz; //size of array
{
std::cin >> sz; //getting size
int* arr = new int[sz]; //declaring variable array.
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning values to all members of array
std::cout << arr[i] << std::endl; //printing the array
}
delete [] arr; // << Delete old one here, missing in original
}
{
std::cin >> sz; //size changes again
int* arr = new int[sz];
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning new values
std::cout << arr[i] << std::endl; //printing the array
}
delete [] arr; // <<--- Here as well, missing in original - less important, but leads to memory leak.
}
or just use std::vector<int> arr(sz); and you can ignore the delete. If you absolute need to re-use the array use arr.resize(sz);

How to free dynamically allocated vector?

I tried to create vector of vector int, and I confused how do i free the dynamically allocated vector after.
The following is my code:
vector<int> *j;
vector< vector<int> > i; //vector of vector<int>
int c; //offset of the number
cin.ignore();
for(int count = 0; count < cas; count++ )
{
c = 0;
char line[1000];
j = new vector<int>;
cin.getline(line, 1000);
//tokenize the input string which separate by space “ ”
char *p = strtok(line, " ");
while(p != NULL)
{
n[c] = string(p);
c++;
p = strtok(NULL, " ");
}
//convert the string input to integer for further calculation
for(int m = 0; m < c; m++)
{
(*j).push_back(atoi(n[m].c_str()));
}
i.push_back(*j);
}
//this is the way i try to free the allocated vector, and i get segmentation fault for this
j = &i[0];
delete [] j;
You don't need any pointers or new or delete. These are advanced concepts that have no place in this simple program.
vector<vector<int>> i;
for (...) {
vector<int> j;
// fill up j
i.push_back(j);
}
Remember, a vector of vectors is not conceptually different from a vector of ints. You don't start new'ing and delete'ing ints when you need to fill up a vector<int>. Nor do you need to do so for any X when you work with a vector<X>.
The
i.push_back(*j);
does't push the pointer; it makes a copy of the vector.
As soon as you've done that, you can
delete j;
there and then.
(Of course if you change i to store pointers, the story will be completely different.)

Deleting dynamic char** in C++

Disclosure: I'm trying to solve a challenge with strict time and memory limits. I would normally use vectors and strings, but here I need the fastest and smallest solution (with vectors it actually ran above the time limit), so I turned to dynamic arrays of char*.
The relevant parts of my code:
char** substrings(string s, int* n){
*n = 0;
...
////////////////////////////////
char** strings = new char*[*n];
////////////////////////////////
for (int i = 0; i < s.length(); i++){
for (int j = 1; j < s.length() - i + 1; j++){
...
strings[si] = tmp;
...
}
}
return strings;
}
int main(){
...
for (int ti = 0; ti < t; ti++){
cin >> s;
char** substr = substrings(s, &n);
...
for (int i = 0; i < n; i++){
delete substr[i];
}
}
return 0;
}
Everything runs just fine without deleting the array (of arrays), but that is unacceptable, so how do I go about this? I've tried a lot of variations that seemed logical but I get runtime errors.
It is similar to allocating, but in reverse order, and using delete[] instead of new[]:
for(int i = 0; i < LENGTH; i++)
delete[] strings[i]; // delete each pointer in char** strings
delete[] strings; // finally delete the array of pointers
I assumed here that LENGTH is the length of the array of pointers to char*. So it looks that you only perform the first round of de-allocation
for (int i = 0; i < n; i++){
delete substr[i]; // need delete[] substr[i] here
but with delete instead of delete[], you need delete[] substr[i] instead, as my guess is that substr[i] is a char* pointer pointing the first element of an array of chars allocated by new[]. You finally need the additional
delete[] substr;

Deleting Arrays With Pointers--Multidimensional and Multipointer---in C++

So I know multiple dimensions/arrays can get confusing, but how do I delete these types of arrays properly? I know the syntax, but adding multiple dimensions/pointers gets tricky. Here's some snippet code:
//FIRST PROBLEM
//function to add an item to a pointer array
//due to problems in adding something directly, I created a temp
//temp is not necessary if there's a way without it
int y = 6;
int x = 5;
int *myList = new int[x];
void List::add(int newInt)
{
void List::add(int newInt){
int *temp = new int[x+1];
temp = myList;
temp[x+1] = newInt;
delete [] myList;
int *myList = temp;
}
//SECOND PROBLEM----tricky multidimensional
// not getting any errors, but not sure if done properly
int x;
int y;
int** myMatrix;
cout << "How many rows?" << endl;
cin >> x;
myMatrix = new int*[x];
cout << "How many columns?" << endl;
cin >> y;
for (int i=0; i<x; i++)
myMatrix[i] = new int[y];
for(int i=0; i<10; ++i){
for(int j=0; j<10; ++j){
myMatrix[i][j] = rand();
}
for(int i = 0 ; i < x ; ++i)
{
for(int j = 0 ; j < col ; ++j){
// delete[] myMatrix[i][j]; (tried this method, did not work)
}
delete[] myMatrix[i];
}
delete[] myMatrix;
//looked around for examples, but were all different enough to not help
//
// delete[] myMatrix[i][j]; (tried this method, did not work)
The code you have here
myMatrix[i][j] = rand();
doesn't allocate any new heap memory for myMatrix[i][j] (which is of a non pointer type, but a simple int BTW), but just assigns the result of rand() as a value there.
Thus it's not necessary/wrong, you ever call delete for it.
You only call delete/delete[] as counterparts of new/new[] in the reverse order as they were allocated.
Further, to get redeemed from struggling with memory management, I'd seriously recommend using a c++ standard container like std::vector<std::vector<int>> myMatrix; instead of managing raw pointers.

How to deallocate a int*** in c++

How do I deallocate this type of 3D array in c++? I have a class that has a int*** volume as a member and I filled it this way..
volume = new int**[xSize];
for(int i =0; i<xSize; i++)
{
volume[i] = new int*[ySize];
for(int j =0; j<ySize; j++)
{
volume[i][j] = new int[zSize];
for(int k = 0; k<zSize;k++)
{
volume[i][j][k] = 0;
}
}
}
You just reverse your actions (other than the filling of the array)
for(int i =0; i<xSize; i++)
{
for(int j =0; j<ySize; j++)
{
delete[] volume[i][j];
}
delete[] volume[i];
}
delete[] volume;
If you can, avoid manual dynamic memory management in the first place. E.g. using std::vector:
typedef std::vector<int> Vec1D;
typedef std::vector<Vec1D> Vec2D;
typedef std::vector<Vec2D> Vec3D;
Vec3D volume(xSize, Vec2D(ySize, Vec1D(zSize, 0)));
As pointed out in the comments, Boost.MultiArray is a convenient alternative.
You need to recursively iterate through all levels of the structure the same way as above (except the innermost level), and delete each element in reverse order compared to their allocation:
for(int i =0; i<xSize; i++)
{
for(int j =0; j<ySize; j++)
{
delete[] volume[i][j];
}
delete[] volume[i];
}
delete[] volume;
In reverse.
You need the same loop structure, but for every new[], you need a delete[] instead, and now nested stuff must occur before outer stuff.
So:
int **x = new int*[M];
for (i = 0; i < M; i++)
{
x[i] = new int[N];
}
becomes:
for (i = 0; i < M; i++)
{
delete [] x[i];
}
delete [] x;
Easy - Just do the steps in reverse
i.e. delete all those volume[i][j] that you have created
Then volume[i] for all i values
Then volume.
It is a bit like losing your keys - you just need to retrace your steps!
The general rule is this: you need to have one matching delete[] for each and every new[]. You seen to have one instance of new int**[], xSize instances of new int*[], and ySize instances of new int[].
So, you might free them all thus:
for(int i =0; i<xSize; i++)
{
for(int j =0; j<ySize; j++)
{
delete[] volume[i][j];
}
delete volume[i];
}
delete[] volume;