Consider the code (it has no meaningful purpose):
double* create() {
double *array = new double[100]; // 1)
for(unsigned int i=0; i<100; ++i) array[i] = i;
return array;
}
double reduce(double* array) {
double sum = 0.0;
for(unsigned int i=0; i<100; ++i) sum += array[i];
return sum;
}
int main()
{
double sum = 0.0;
for(unsigned int i=0; i<100; ++i) {
sum += reduce(create());
}
// 2)
// ...
}
Are the arrays created in 1) during the for-loop still on the heap at point 2) i.e. is some memory still being (unnecessarily) occupied at point 2)?
(I know that the example could be more minimalistic but it is really short.)
The array is still in the heap but the pointer to the array is lost. As a result there is a memory leak.
So you should split the calls of the functions introducing a variable that will store the pointer returned from the function create that then you could use the variable to free the allocated array.
That is the array with the dynamic storage duration will be destroyed when the operator delete [] will be called. Or the memory will be freed when the program will finish its execution.
Related
I try to clean the memory to delete pointers. But the last instruction (delete array[i]) generate this error :
pointeurs-tableau(14994,0x110a67600) malloc: *** error for object 0x7ff7bb760760: pointer being freed was not allocated
But I don't know why.
#include <iostream>
#include <random>
#include <ctime>
using namespace std;
int main()
{
default_random_engine gen(time(0));
uniform_int_distribution<> dis(1, 100);
const int max = 20;
int* array[max];
// un tableau normal
int val[max];
for (int i = 0; i < max; i++) {
val[i] = dis(gen);
}
for (int i = 0; i < max; i++)
{
array[i] = &val[i];
}
//... modifying function on the array
// show the array
for (int i = 0; i < max; i++) {
cout << val[i] << " ";
}
// deleting pointeurs (problematic !!!!)
for (int i = 0; i < max; i++)
{ delete array[i];}
delete[] array;
return 0;
}
Could you help me, please?
delete operator must be used only on a dynamically allocated memory (with the new).
In your case you have an array int val[max]; with automatic storage duration. And array of pointers int* array[max]; also with automatic storage duration.
Automatic storage duration means memory for arrays int val[max]; and int* array[max]; will be allocated when execution enter in the scope they declared and will be freed when execution lives the scope (at your case main function).
But when you trying to call delete array[i]; you force compiler to attempt clear element from int val[max] onto which array[i] pointing to. But it can't do that because this value never have been allocated on the heap with new.
// Edit
As you mentioned in comment to this answer you added changes to your code:
int **array = new int*[max];
for (int i=0; i < max; i++) {
array[i] = new int;
}
An still have the same error;
The reason behind it most likely is that you still have this cycle
for (int i = 0; i < max; i++) {
array[i] = &val[i];
}
int** array; item: array[i] - is a pointer.
You allocated memory on the heap and stored address of this memory into that pointer:
array[i] = new int;
Lets say new int; returned address ADDRESS_FROM_HEAP
Then you took address of int val[max]; by &val[i] and assigned it to the pointer array[i] = &val[i];
Lets say &val[i] equal to ADDRESS_FROM_STACK
Then you trying to delete array[i];
But at this moment array[i] == ADDRESS_FROM_STACK;
Not only delete unable to free memory on ADDRESS_FROM_STACK, you also lost ADDRESS_FROM_HEAP and memory by this address will not be freed.
If you would change your loop to this
for (int i = 0; i < max; i++) {
*array[i] = val[i];
}
You will store a COPY of val[i] in the memory pointed by array[i] pointer.
But by looking at your code I can't honestly see why you allocate any memory dynamicly.
If you will just leave code as it is in your original question and just remove all delete statements, it will work just fine.
I need to be able to do this without using C++ smart pointers. I tried the following
double* VecToArr(std::vector<std::vector<double>> vec) {
double* newarr=new double(vec.size());
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
std::cout<<"inside \n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"\n";
}
return newarr;
}
int main(){
std::vector<double> x{1,2};
std::vector<double> y{3,4};
std::vector<std::vector<double>>vec;
vec.push_back(x);
vec.push_back(y);
double *arr=VecToArr(vec);
std::cout<<"outside \n";
for (int i=0; i<4; i++) {
std::cout<<arr[i]<<"\n";
}
}
But inside the VecToArr, the output is:
inside
4.54e-322 2.18e-317 4.34e-311 4.24e-314
not 1 2 3 4 like I expected
And outside it, I get the same garbage values. Why is this?
Also, since I used new to create newarr inside VecToArr, where how do I delete it? In main.cpp, after I print out the values, do I just do delete arr[]?
EDIT
When I change the function to:
double* VecToArr(std::vector<std::vector<double>> vec) {
double* newarr=new double[vec.size()*vec[0].size()];
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
std::cout<<"inside \n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"\n";
}
return newarr;
}
The output is now 3 4 (garbage) (garbage) instead of 1 2 3 4.
The three main problems are as others have mentioned in the comments and a bit more. Firstly, you're using the wrong type of new expression, new double(...) simply allocates memory for a single double and initializes it with the value of what was provided. You probably want new double[...] to allocate an array of the doubles.
Secondly, the size provided to this new is incorrect, only representing the first dimension of the vector (when it needs to be a sum of all the nested vectors' sizes).
Finally, you're returning newarr, which has been modified by the for loop inside the function and ends up pointing to the memory after where the allocation took place, you'll likely want to make a temporary copy of it at the start and return that instead.
With all the changes the final correct function may look like this:
double* VecToArr(std::vector<std::vector<double>> vec) {
std::size_t totalsize = 0;
for (int i=0; i<vec.size(); i++) {
totalsize += vec[i].size();
}
double* newarr=new double[totalsize];
double* walkarr=newarr;
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), walkarr);
walkarr += vec[i].size();
}
return newarr;
}
I'd also recommend passing the vector in by constant reference as currently it is being passed by value for (currently) no reason which may result in unnecessary overhead. Additionally, you should try to always use something like std::vector (or at least smart pointers) for allocation of memory rather than using new/delete directly (unless dealing with low level container implementation) as there is usually not much reason to at the expense of opening the program up to memory leaks.
There are issues with memory allocation, indexing and pointer arithmetic. I have pointed out those in your code.
#include <iostream>
#include <vector>
double* VecToArr(const std::vector<std::vector<double>>& vec) {
double* newarr=new double[vec.size() * vec[0].size()]; // <-- you have 4 elements (also notice square brackets)
double* newarr_ptr_copy = newarr;
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr_ptr_copy);
newarr_ptr_copy += vec[i].size(); // don't lose track of newarr
}
std::cout<<"inside \n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"\n";
}
return newarr;
}
int main(){
std::vector<double> x{1,2};
std::vector<double> y{3,4};
std::vector<std::vector<double>>vec;
vec.push_back(x);
vec.push_back(y);
double *arr=VecToArr(vec);
std::cout<<"outside \n";
for (int i=0; i<4; i++) {
std::cout<<arr[i]<<"\n";
}
delete [] arr; // make sure that you release the memory that you allocated
}
Look at this piece of code:
double* newarr=new double[vec.size()];
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
A simple math fells violated here. You allocate your newarr to be the size of vec. So far so good. Now, for each element in vec you increment the pointer by vec[i].size - effectively leading to the used size of SUM(vec[i].size()). This is not right, you have undefined behavior in your program by accessing array outside of it's allocated bounds.
Please note, I also fixed a typo in your code - your original version of new double(vec.size()) allocated a single double, not an array of them.
I have a function that takes in an array and defines a new array made up of a subset of the original array.
#include<iostream>
#include<cmath>
using namespace std;
double * subarray(double *array){
double *sub= new double[100];
for (int i=0; i<10; i++){
sub[i]=array[i];
}
return sub;
}
int main(){
double *x=new double[100];
double *y=new double[10];
for(int j=0; j<100; j++){
x[j]=sin(j*3.14/2.0);
}
y=subarray(x);
for(int k=0; k<10; k++){
cout<<y[k]<<endl;
}
return 0;
}
When I run this code some of the elements of the sub array come out as nan.
calling subarray is creating a new double[100] then passing that back out. But it's a completely separate array to y = new double[10]. Whenever you call "new" it's making a new thing, separate to all other "new" things. y gets the address of the "new double[100]" but it loses track of the address of the "new double[10]" you made in main, which is a memory leak. If you're going to return a pointer to an new'ly allocated item, start the pointer that's going to store it as a nullptr, and call "delete" or "delete []" when you're done, depending on whether it was a "new[]" thing or just "new".
#include<iostream>
#include<cmath>
using namespace std;
double * subarray(double *array) {
double *sub = new double[10]; // don't allocated more than you want to use
for (int i = 0; i < 10; i++) {
sub[i] = array[i];
}
return sub;
}
int main() {
double *x = new double[100];
double *y = nullptr; // don't set this if you're going to overwrite it
for (int j = 0; j < 100; j++) {
x[j] = sin(j*3.14 / 2.0);
}
y = subarray(x);
for (int k = 0; k < 10; k++) {
cout << y[k] << endl;
}
delete [] x; // if you make new things, delete them afterwards
delete [] y;
std::cin.get();
return 0;
}
I don't get any NaNs when I run this, but you are allocating a lot of memory that never gets set, inside the function. You're allocating 100 spaces but only writing to 10. This isn't necessarily an error, but it's not efficient.
The following snippet of code is my attempt to increase the size of an array by a factor of two. I am having several problems with it. Most importantly, should I be calling delete on my original array?
void enlarge(int *array, int* dbl int size) {
for (int i = 0; i < size; i++)
dbl[i] = array[i];
delete array;
array = dbl;
}
You have a few problems:
Modifying array only modifies the local copy of the pointer. You need to take a reference-to-pointer if you want the modification to be observed by the calling code.
You need to use delete[] when deleting things allocated with new[].
You attempt to copy too many items, and in so doing you overrun the original array.
void enlarge(int *& array, int size) {
// ^
// Use a reference to a pointer.
int *dbl = new int[size*2];
for (int i = 0; i < size; i++) {
// ^
// Iterate up to size, not size*2.
dbl[i] = array[i];
}
delete[] array;
// ^
// Use delete[], not delete.
array = dbl;
}
However, I would strongly suggest using std::vector<int> instead; it will automatically resize as necessary and this is completely transparent to you.
keyword double cannot be used as variable name, and previous array must be deleted before new allocation get assigned to same pointer, and loop should copy size no of items from prev array (not 2 * size)
void enlarge(int **array, int size) {
int *d = new int[size*2];
for (int i = 0; i < size; i++)
d[i] = *array[i];
delete [] *array;
*array = d;
}
if previous array was int *arr, and size is the currentsize of the array arr, call should be as: enlarge(&arr, size)
How can I dynamically allocate a two dimensional array where each row contains variable element? How can I free this memory?
Actually you probably want a vector of vectors, something like this:
std::vector<std::vector<int> > vector_2d;
This way you'll benefit from the automatic memory management of the vector rather than having to manually manage the memory of an array of pointers to arrays of data.
You would need need to use pointers:
int ** a;
a = new (int*)[5];
for(int i = 0; i<5; i++)
{
a[i] = new int[x]; //where x is the size of this row
}
Something like this should work, but I didn't test it.
Just for the sake of completeness:
int ** a;
a = new (int*)[5];
for(int i = 0; i<5; i++)
{
a[i] = new int[x]; //where x is the size of this row
}
for(int i = 0; i<5; i++)
{
delete[] a[i];
}
detete[] a;