I have this in my code:
double** desc = new double* [size_out];
for (int i = 0; i < size_out; i++)
desc[i] = new double [size_in];
How do I delete this desc?
Should I do:
delete [] desc;
or
for (int i=0; i<size_out; i++)
delete [] desc[i];
delete [] desc;
or
for (int i=0; i<size_out; i++)
delete [] desc[i];
delete desc;
?
Simple rules to follow:
for each allocation, there has to be a deallocation (ex1 is therefore wrong)
what was allocated using new should be freed using delete, using new[] should be deallocated using delete[] and using malloc should be deallocated using free (ex3 is therefore wrong)
Conclusion, ex2 is OK.
Your code shouldn't compile. The type of an array new expression is a pointer to the type of array element being created (the value is a pointer to the first element of the allocated array).
So the type of new double**[size_out] is double ***.
Whenever you use the array form of new, you must use the array form of delete even if you only allocate an array of size one.
double*** desc = new double**[size_out];
for (int i=0; i<size_out; i++)
desc[i] = new double*[size_in];
for (int i=0; i<size_out; i++)
delete[] desc[i];
delete[] desc;
Note that you still haven't allocated any double, just pointers.
Did you really want this instead?
double** desc = new double*[size_out];
for (int i=0; i<size_out; i++)
desc[i] = new double[size_in];
for (int i=0; i<size_out; i++)
delete[] desc[i];
delete[] desc;
Your deletion should mirror your allocation.
Since you used new [] to allocate the outer array, and new [] (in a loop) to allocate the inner arrays, do likewise for deletion. That is: your second solution is correct; delete [] the inner arrays in a loop, and finally the outer array via delete [] also.
That said, a (much, much) better solution in C++ would be to use a nested std::vector:
// Declaration and initialization:
vector<vector<double> > desc(size_out, vector<double>(size_in));
// No deletion!
Solution 2 is the right one : each cell points to a dynamically allocated array that should be deleted using delete[]. Finally,
the desc array itself should be deleted using delete[].
Bonus solution 4 : avoid using arrays and switch to std::vector<std::vector<double> >.
I would do
for (int i=0; i<size_out; i++)
delete [] desc[i];
delete [] desc;
for each array allocated with new [], you have a corresponding delete [].
And as Rupdolph says: stop using C-arrays, and start using std::vector. You will have less bugs (hundred times less bugs).
Related
I am using Dr. Memory to debug my code. It gives me the following message:
INVALID HEAP ARGUMENT: allocated with operator new[], freed with operator delete
However, whenever I use delete[] instead of delete, it gives me the same error. The error occurs in the following lines:
for (int x = 0; x < width; ++x)
{
delete data[x];
}
delete [] data;
Variable data is being allocated as follows:
data = new char*[width];
for (int i = 0; i < width; ++i)
{
data[i] = new char[1];
}
Could someone please help me out?
You currently allocate the elements with
data[i] = new char[1];
and delete them with
delete data[x];
As you allocated them with the new[] you need to delete them with delete [].
delete [] data[x];
You need to match the second new[] (data[i] = new char[1]) too:
for (int x=0; x<width; ++x){
delete [] data[x];
}
delete [] data;
Since you are using c++, and not C...
Re-factor the code to use the STL and std::string to create vectors of std::strings in the program.
Use of std::string will likely eliminate the memory leak.
Okay, I'm writing a program that will perform different functions on an array. If necessary, the array will need to change capacity. The instructions are:
Create an new array.
Copy the contents from the old array to the new.
Delete the old array.
This part is understand, but what I don´t understand is how to keep a reference to the array that the functions will work with. This is my code for creating a new array and move over the elements.
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
delete []tempArray;
}
All the other methods use arr so I would like to reference back to that. A pointer won´t work since it only points to the first element. How can I use my arr variable to refer to an array?
In C and C++ dynamic arrays are usually represented by a pointer to the first element and the number of elements. So I'm assuming the following declarations:
double *arr;
int m_size;
If by any chance you have arr decleared as a real array double arr[..], then you cannot do delete []arr nor change its size!
Then your code should be along the lines of:
int newSize = 2*m_size;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
arr = tempArray;
m_size = newSize;
But now I wonder: why m_size-1 in the loop?
And also, you can just do:
memcpy(tempArray, arr, sizeof(*arr) * m_size)); //or m_size-1?
All this is nice if it is an exercise. For real code it almost always better to use std::vector<double> and the resize() member function.
You got undefined behaviour in your code.
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
You delete the memory arr was pointing to and then assign to the deleted memory inside the loop. Instead you should just write:
delete []arr;
arr = tempArray;
The whole code would be:
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++) // -1 might be wrong, look below for a comment on this line.
{
tempArray[i] = arr[i];
}
delete []arr;
arr = tempArray;
m_size = newSize // stolen from the others *cough* since I oversaw the need.
// note that I don't call delete on tempArray.
}
Also I don't know how you allocated your first array but if you made it calling new double[m_size] then you'd want to delete the -1 in the loop condition of the for loop since you're checking for i < m_size and not i <= m_size.
You need to allocate memory for ar after deallocating it.
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
ar = new double[newSize];
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
delete []tempArray;
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
Oops. Don't access after delete. And don't delete unless it was allocated with new.
You simply can't reallocate an array declared as
int arr[100]
or similar.
Based on the code you've given, what you're currently performing is:
Create a new array (tempArray)
Copy the contents of the old (arr) array to the new (temp) - (note - what happens if you make the new array smaller than the old?)
Delete the old array
Copy the new values back into the deleted remains of the old array (note - you deleted arr so you can't use it now!)
Delete the new array (so everything is gone)
Basically, you need to fix step 2, to handle sizes, and get rid of steps 4 and 5 entirely - you just need to re-assign arr instead:
arr = tempArray
You just have to declare the array arr and put the values in it. You can refer to the array through its pointer arr or each element with arr[element_id].
You have a couple of options here:
Take the C-style approach of just storing the pointer to the first element like you have, plus the length. From those two you can calculate anything you need.
Use std::vector. It holds an array, allows you to easily resize it with functions like emplace_back, and can tell you its length with the size function.
The second approach is certainly preferred. If you're in C++, you should usually be using std::vector instead of raw arrays, unless you're looking for a fixed-sized one. In that case use std::array.
You also get the added benefit of copying a vector being as simple as vector1 = vector2;.
I've searched through many topics here, but they didn't seem to answer me exactly.
I'm trying to do some dynamic reallocation od arrays in C++. I can't use anything from STL libraries as I need to use this in homework where STL (vectors,...) is explicitly forbidden.
So far, I've tried to elaborate with code like this:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //is this necessary to delete?
items = new int [10];
for (int i = 0; i < 10; i++) items[i] = temp[i];
delete [] temp;
This seem to work, but what bothers me is the excessive number of iterations. Can't this be done anyhow smarter? Obviously, I'm working with much larger arrays than this. Unfortunately, I have to work with arrays though.
edit: When I try to do items = temp; instead of
for (int i = 0; i < 10; i++) items[i] = temp[i]; and try to std::cout all my elements, I end up with losing first two elements, but valgrind prints them correctly.
Yes, the first delete[] is necessary. Without it, you'd be leaking memory.
As to the code that comes after that first delete[], all of it can be replaced with:
items = temp;
This would make items point to the ten-element array you've just populated:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //delete the original array before overwriting the pointer
items = temp;
Finally, don't forget to delete[] items; when you are done with the array.
The containers of the STL were made to ease work like this. It is tedious, but there is not much of a choice, when you need to use C-arrays.
The deletion of
delete [] items;
is necessary, as when you abandon the reference to the array, which you would do with assigning a new reference in
items = new int [10];
will cause a memory leak, so this is necessary.
I have a double array allocated by pointer to pointer.
// pointer to pointer
int **x = new int *[5]; // allocation
for (i=0; i<5; i++){
x[i] = new int[2];
}
for (i=0; i<5; i++){ // assignment
for (j=0; j<2; j++){
x[i][j] = i+j;
}
}
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
I am trying to do this using unique_ptr:
std::unique_ptr<std::unique_ptr<int>[]> a(new std::unique_ptr<int>[5]);
for (i=0; i<5; i++)
a[i] = new int[2];
but kept getting an error saying that no operator = matches these operands. What I am doing wrong here?
You cannot assign a int* to a std::unique_ptr<int[]>, that is the cause for your error. The correct code is
a[i] = std::unique_ptr<int[]>(new int[2]);
However, piokuc is correct, that it is highly unusual to use unique_ptr for arrays, as that's what std::vector and std::array are for, depending on if the size is known ahead of time.
//make a 5x2 dynamic jagged array, 100% resizable any time
std::vector<std::vector<int>> container1(5, std::vector<int>(2));
//make a 5x2 dynamic rectangular array, can resize the 5 but not the 2
std::vector<std::array<int, 2>> container1(5);
//make a 5x2 automatic array, can't resize the 2 or 5 but is _really fast_.
std::array<std::array<int, 2>, 5> container;
All of these can be initialized and used just the same as the code you already had, except they're easier to construct, and you don't have to destroy them.
If you do not have the luxury of using a std::array or a std::vector instead of a dynamically allocated array, you can use a std::unique_ptr for a two-dimensional array in C++11 as follows:
std::unique_ptr<int*, std::function<void(int**)>> x(
new int*[10](),
[](int** x) {
std::for_each(x, x + 10, std::default_delete<int[]>());
delete[] x;
}
);
The unique_ptr declaration takes care of allocating the row dimension of the array. The trailing () in new int*[10]() ensures that each column pointer is initialized to nullptr.
A for loop then allocates the column arrays:
for (size_t row = 0; row < 10; ++row) {
(x.get())[row] = new int[5];
}
When the unique_ptr goes out of scope, its custom deleter lambda function takes care of deleting the column arrays before deleting the row array. The for_each expression uses the default_delete functor.
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
NO NO NO NO
delete [] x[i];
delete [] x;
// yo
The only reasons I can think of to use std::unique_ptr (or say boost::scoped_array) over std::vector for holding arrays are usually not applicable...
1) it saves 1 or 2 pointers worth of memory, depending on if you know what the size of all the arrays is [irrelevant unless you have a massive number of very small arrays]
2) in case you are just passing the array into some function that expects a C style array or raw pointer, it may feel like a more natural fit. std::vector IS guaranteed to be on sequential storage though, so passing (a.empty() ? nullptr : &a[0], a.size()) into such a function is 100% legit as well.
3) standard containers in MSVC debug mode are "checked" by default and very slow, which might be annoying when doing scientific programming on large datasets.
Your code is effectively manipulating an array of arrays of int.
In C++ you would normally want to implement it as:
std::vector<std::vector<int> > x;
This is not a good case for unique_ptr. Also, you should not need to use pointers to unique_ptr and allocate unique_ptr objects dynamically. The whole point of unique_ptr is to eliminate usage of pointers and to provide automatic allocation and deallocation of objects.
#include <iostream>
#include <memory>
#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl
int main() {
std::unique_ptr<std::unique_ptr<int[]>[]> arr(new std::unique_ptr<int[]>[2]());
for (int i = 0; i < 2; i++)
{
arr[i] = std::make_unique<int[]>(5);
for (int j = 0; j < 5; j++) {
arr[i][j] = j;
println(arr[i][j]);
}
println(arr[i]);
}
}
An example further up inspired me for this solution
size_t k = 10;
std::unique_ptr<int*, std::function<void(int**)>> y(new int*[k](),
[](int** x) {delete [] &(x[0][0]);
delete[] x;});
// Allocate the large array
y.get()[0] = new int[k*10];
// Establish row-pointers
for (size_t row = 0; row < k; ++row) {
(y.get())[row] = &(y.get()[0][0]);
}
Here all dimensions can be dynamic and you can wrap it inside a class and expose an operator[]. Also the memory is allocated in a contiguous manner and you can easily introduce an allocator, which allocates aligned memory.
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
It is a common mistake here.
x[i] is an array so you have to delete each array first using delete[]
Then you can delete you array of int* by using delete[]
Correct desallocation would be:
for (i=0; i<5; i++)
delete[] x[i]; //desallocate each array of int
delete[] x; //desallocate your array of int*
x = nullptr; //good practice to be sure it wont cause any dmg
I've a 3x3 2D dynamic array allocated as below:
int** matrix = new int* [3];
matrix[0] = new int [3*3];
for (int i = 1; i < 3; ++i)
matrix[i] = matrix[i-1] + 3;
How should I deallocate it? Is this correct:
delete [] matrix;
delete [] matrix[0];
Or should I also delete matrix[1], [2]
The way you have it, you should :
delete [] matrix[0];
delete [] matrix;
But this is a very unconventional way of allocating a dynamic 2D array. Normally you allocate an array of pointers, and then you allocate an array of your actual type for every row (column).
// allocate
int **matrix = new int*[3];
for(int i = 0; i < 3; ++i)
matrix[i] = new int[3];
// deallocate
for(int i = 0; i < 3; ++i)
delete [] matrix[i];
delete [] matrix;
You'll need one delete for each new, in reverse order of the new's.
The code:
delete [] matrix;
delete [] matrix[0];
is obviously wrong, as you use matrix after you delete it.
delete [] matrix[0];
delete [] matrix;
is correct, but I can't vouch that the code as whole does something sensible.
Note that you should not delete matrix[1] and matrix[2] as they are just copies of matrix[0]. A rule of thumb is that you should have the same number of calls to delete as you have calls to new.
You need to read this: http://isocpp.org/wiki/faq/freestore-mgmt#multidim-arrays
In a nutshell, allocate your matrix in a single chunk if it is rectangular:
int* matrix = new int[3*3];
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
matrix[i*3+j] = x;
delete [] matrix;
Since it's allocated in one chunk you can also delete in one chunk.
Or you can do something similar to what you're doing, but do an allocation for each row. Be sure to delete each row first, then the matrix.
The linked article also has info about wrapping up the nasty pointer/array stuff in a class.
The array of pointers may be unnecessary. You could just allocate the 1D array of 9 elements and do the math to convert 2D indexes to 1D indexes.
In addition to swapping around the delete[] operations, you should consider what happens when an allocation fails. If the second allocation throws std::bad_alloc, your program leaks the memory from the first allocation. A correctly-written matrix class (as suggested by Fred Larson) would handle memory deallocation for you.
Every element in the matrix array is an int[], in addition to that, matrix itself is an array of int* (int*[]), taking these rules into account you should do
delete [] matrix[i] { i=0,1,2 }
and then do
delete [] matrix to delete the matrix itself.
Hope this helps.
Thanks