When I have an array like this:
int* test = new int[50];
for (int i = 0; i < 50; i++)
{
test[i] = dist4(rng);
}
(Filled with random numbers for testing)
I can free the memory like this:
delete[] test;
But when I declare the array like this:
int test[50];
for (int i = 0; i < 50; i++)
{
test[i] = dist4(rng);
}
I can't free the memory with delete or delete[].
What's the proper way of freeing the memory here?
The "dist4" function is just a random number generator:
random_device dev;
mt19937 rng(dev());
uniform_int_distribution<mt19937::result_type> dist4(1,4); // distribution in range [1, 4]
What's the proper way of freeing the memory here?
No need to free memory explicitly using delete or delete[] in the latter case.
Assuming int test[50]; is declared inside a function, it has automatic storage duration and when test goes out of scope it will be automatically destroyed.
The memory will automatically be freed when it does out of scope like any other non-dynamically allocated variable. This is due to automatic storage duration
Write the code like this using a local scope:
void a_function ()
{
// some code
{
int test[50];
for (int i = 0; i < 50; i++)
{
test[i] = dist4(rng);
}
}
// here the space for test will recovered.
// some more code...
}
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.
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.
I have some pointers that I allocate in the constructor of a class and then attempt to delete in its destructor:
TileMap::TileMap(int x, int y) {
mapSize.x = x;
mapSize.y = y;
p_p_map = new Tile*[x];
for(int i = 0; i < x; i++) {
p_p_map[i] = new Tile[y];
}
randomize();
}
TileMap::~TileMap() {
for(int i = 0; i < mapSize.x; i++) {
delete p_p_map[i];
}
delete p_p_map;
}
void TileMap::randomize() {
for(int i = 0; i < mapSize.x; i++) {
for(int j = 0; j < mapSize.y; j++) {
p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());
}
}
}
At the end of the program the destructor is called to free the memory of the pointers I allocated, but when it reaches "delete p_p_map[i];" in the destructor, XCode informs me that the pointer was not allocated. I am new to C++, but I feel that I pretty explicitly allocated memory to the pointers in the randomize() function.
What error am I making?
You have to match delete with new and delete[] with new[]. Mixing one up with the other leads to issues. So if you do:
p_p_map = new Tile*[x];
you have to delete it like:
delete[] p_p_map;
and same with
delete[] p_p_map[i];
If you create something like:
pSomething = new Type;
then you delete it like:
delete pSomething;
What error am I making?
A few:
First, as #uesp pointed out, you mismatch new and delete calls
Second, you are using the "memory leak operator":
p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());
The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].
Because the pointer is not stored anywhere, it is leaked.
Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.
For example, here's what happens if you construct a Tile instance with large values for x and y:
TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)
mapSize.x = x;
mapSize.y = y;
p_p_map = new Tile*[x]; // allocate 1049600 pointers block
for(int i = 0; i < x; i++) {
p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop
}
randomize();
}
Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.
In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.
To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as #CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).
I am trying to pass an array to constructor in C++ but it is not working:
arrayClass(int *array,int size){
a = new int[15];
for(int i(0); i < size; i++) {
this->a[i] = array[i];
}
this->size = size;
cout << "In second constructor" << endl;
}
in main()
int array[3]={1,2,3};
arrayClass a2(array,3);
Your example is working fine - just take care to delete[] with new[] allocated space accordingly after you're finished (to prevent memory leaking). Also instead of using 15 as hardcoded constant, you probably want to use the parameter size (otherwise for arrays bigger than 15 elements, you would have an memory access violation).
class ArrayClass{
public:
ArrayClass(int* array, int size){
a = new int[size];
for (int i(0); i < size; i++) {
this->a[i] = array[i];
}
this->size = size;
}
virtual ~ArrayClass(){
delete[] a;
}
private:
int* a;
int size;
};
int main(int argc, char** argv){
int array[3] = { 1, 2, 3 };
ArrayClass a2(array, 3);
return 0;
}
Arrays can be allocated in C++ in different ways:
int a[3]; // will allocate the space for 3 elements statically from the stack
int* a = new int[3]; // will allocate space for 3 elements dynamically from the heap
Basically it decides in which memory your array will be located - but there are many differences in these two methods involved - see i.e. What and where are the stack and heap?.
Some main differences are:
stack allocations can't use a dynamical length like a variable i.e. int size = 10; int a[size]; // <- is invalid
stack allocations are 'deleted' automatically when they are out-of-scope
heap allocations have to be deleted[] explicit to not leak memory
The line int* a = new int[3]; will declare a pointer-variable to an memory location where 3 int values can fit in. So after the declaration these 3 values can be addressed directly as a[0], a[1] and a[2]. After all operations are finished delete[] a; is necessary. Because if the pointer a* is getting out-of-scope (i.e. end of your function) the memory for the 3 values is not deallocated automatically.
I've got the following code:
jobjectArray objects; //function argument, actually a byte[][]
jbyteArray* arrays = malloc(sizeof(jbyteArray), 2); // Assume 2
for(int i = 0; i < 2; ++i) {
arrays[i] = (jbyteArray)env->GetObjectArrayElement(objects, i);
}
// Do stuff with arrays.
// Do I have to do this?
// for(int i = 0; i < 2; ++i) {
// env->DeleteLocalRef(arrays[i]);
// }
free(arrays);
Is this enough to avoid leaking memory / keeping stray references? Or should I also be calling DeleteLocalRef?
edit:
I did find this reference at the help for IBM SDK for Java which states that they are automatically cleaned up when the function returns to Java. But if there is no automatic garbage collection, references might leak.