Dynamic memory deletion within functions - c++

this is my first post, so sorry if it is not asked well.
Basically I am having trouble with dynamic memory and i would like to know if it is me misunderstanding the concept, or at least one of the functions. Ok, so i'm using C++ where I need to manage an array that changes size within the main program loop but i keep getting a heap error when i try to delete the memory. (below is a simplified version of what i'm trying to do).
void main(void)
{
//Initialization
//main loop
while(true)
{
int* array;
function(&array);
printf("test %d",array[0]); //basically use the data
delete [] array;
}
}
//in separate file
void function(**int val)
{
*val=new int[size of array] // i pass the size of the array...
//to the function as well
//fill the array with data
return;
}
Ok so after this i can read the data so it must be attached to the pointer "array" but then why would it not allow me to delete the data as if it was already deleted?
Any advice would be much appreciated thanx.

Not the main problem but you actually have the syntax wrong here,
void function(**int val);
It should be:
void function(int **val);
But you don't need a double pointer as you can simply pass the pointer by-reference:
void function(int *&val);
It follows that your program should be like this:
int main() // main should return int
{
int *array;
function(array, 5);
printf("test %d", array[0]);
delete [] array;
}
void function(int *&val, int size)
{
val = new int[size];
}
You also didn't need the while (true) loop either.

You said that "any advice" was welcomed, so here's my advice:
Don't use C-style arrays in the first place, and this won't be a problem. Use a vector instead:
#include <vector>
#include <algorithm>
void main(void)
{
//Initialization
//main loop
while(true)
{
std::vector <int> array;
function (array);
printf ("test %d", array[0]);
}
}
//in separate file
void function(std::vector <int>& vec)
{
vec.push_back (1);
vec.push_back (2);
// ...etc...
}
Above is a basic and naive implementation that uses a vector instead of C-style arrays and dynamic memory management. There are many opportunities for improvement, but you get the idea.

Your code, in its current state, should work. However, it is very bad practice to use new and delete like that, especially with new/delete in different places.
You should use std::vector instead:
// main function
std::vector<int> array = function();
printf("test %d",array[0]); //basically use the data
And your function() would be:
std::vector<int> function()
{
std::vector<int> val(size);
//fill the array with data
return val;
}

Another idea. The value in passing things by reference is the copying cost of large objects. With pointers you don't need to worry about this. This code could be cleaned up like this as well.
int main() // main should return int
{
int *array = function(SOME_SIZE);
printf("test %d", array[0]);
delete [] array;
}
int * function(int size) //Just return the pointer
{
int *temp = new int[size];
return temp;
}
Since we're dealing with pointers... returning them isn't a big deal, and is typical practice when you need to "transfer" ownership of a dynamically allocated object. That being said, the post that references using vectors or other standard containers is the best approach. Avoiding use of new and delete makes code much safer.

Related

return pointer with new operator. Where to put delete?

Im fairly new to C++.
So I learned that new allocates memory and returns a pointer of my datatype. But can I use this in a function and return the pointer? If so then where should I place the delete operator?
Is the following code legal?
int *makeArray(int size)
{
int *result = new int[size];
delete[] result;
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... */
return 0;
}
It is compiling and working but logically it makes no sense because I deleted my array.
So I tried the following:
int *makeArray(int size)
{
int *result = new int[size];
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... do some stuff with pointer */
delete[] pointer;
return 0;
}
Is this safe or does it cause a memory leak? Is there a better way of returning the pointer?
I tried both versions and they are compiling and working but I'm sure at least one of them if not both are unsafe.
Is the following code legal?
int *makeArray(int size)
{
int *result = new int[size];
delete[] result;
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... */
return 0;
}
Definitely not! This is Undefined behavior because you return a deleted pointer. After using the delete operator you're telling your OS that it can release the memory and use it for whatever it wants. Reading or writing to it is very dangerous (Program crashing, Bluescreen, Destruction of the milky way)
int *makeArray(int size)
{
int *result = new int[size];
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... do some stuff with pointer */
delete[] pointer;
return 0;
}
Is this safe or does it cause a memory leak?
Yes this is the correct way of using the new and delete operator. You use new so your data stays in memory even if it gets out of scope. Anyway it's not the safest code because for every new there has to be a delete or delete[] you can not mix them.
Is there a better way of returning the pointer?
YES. It's called Smart Pointer. In C++ programmers shouldn't use new but smart pointer at all. There is a C++ community Coding Guideline to avoid these calls Guideline R11

How to prevent memory leak when we "have to" pass pointers in loop to some function?

I am having a situation where I have to call a function in loop with pointer (to a class object) as a parameter. Issue is, I cannot modify the signature of that function and that with every iteration of loop, I have to initialize the pointer. This will lead to memory leak as I cannot delete the pointer (after passing it to the function) inside the loop. Is there any way I can prevent memory leak in such a case?
I would like to explain with a simple example:
class testDelete
{
public:
void setValue(int* val) {vec.push_back(val);};
void getValue();
private:
vector <int*> vec;
};
void testDelete::getValue()
{
for (int i=0;i<vec.size();i++)
{
cout << "vec[" << i << "] = " << *vec[i]<<"\n";
}
}
int main()
{
testDelete tD;
int* value = NULL;
for (int i=0;i<10;i++)
{
value=new int(i+1);
/*I am not allowed to change this function's signature, and hence I am forced to pass pointer to it*/
tD.setValue(value);
/*I cannot do delete here otherwise the getValue function will show garbage value*/
//delete value;
}
tD.getValue();
return 0;
}
If deleteTest wants to use pointers of maybe gone objects it should hold std::weak_ptrs.
Holding on to a raw pointer and dereferencing it later is dangerous (unless you can make sure the object is still alive, a.k.a don't use raw but smart pointers).
[...] I cannot modify the signature of that function and that with every
iteration of loop, I have to initialize the pointer. Is there any way I can prevent memory leak in such a case?
If you need dynamically allocated objects, use smart pointers (eg std::smart_ptr for shared ownership). If you do not need to dynamically allocate them then don't.
For the sake of the example lets assume you cannot modify deleteTest, then for integers there is no reason to dynamically allocate anything
int main()
{
std::array<int,10> x;
testDelete tD;
for (int i=0;i<10;i++)
{
x[i] = i+1;
tD.setValue(&x[i]);
}
tD.getValue();
return 0;
}
Take this code with a grain of salt, it is actually deleteTest that needs to be fixed to avoid creating trouble.
TL;DR
In your example you have actually two problems. deleteTest may try to access already gone objects and memory leaks in main. Using smart pointers solves both.
Store the integers in a container:
int main()
{
std::vector<int> values(10);
testDelete tD;
for (int i=0;i<10;i++)
{
values[i] = i + 1;
tD.setValue(&values[i]);
}
tD.getValue();
return 0;
}

Cannot operate on an array of structures which comprise a string C++

I have a structure which includes a string field. I create an array of those structures and then I want to pass them to a function (by reference). Everything works perfectly fine when I comment out the string field, but if I don't the program crashes. I can't find an answer to this anywhere..
Here's the code (I reduced it to only show the issue):
struct student {
int a;
int b;
string name[20];
char status;
};
void operation(student the_arr[1],int number_of_students) {
delete[] the_arr;
the_arr = new student[3];
for(int i = 0; i<3; i++) {
the_arr[i].a = i+5;
the_arr[i].b = i+4;
}
}
int main() {
student *abc;
abc = new student[0];
operation(abc, 0);
system("pause");
return 0;
}
I need the array to be dynamic so I can change its' size when I need to.
Assuming you can't use std::vector instead of dynamically allocated arrays follow the answer below. In any other case you should use the containers provided by the standard library.
Note: Your program doesn't crash. The only things the compiler will complain about it the allocating zero elements part, but will let you compile and run this program.
Your function is completely wrong. When using dynamic allocation you can simply pass a pointer like this:
void operation(student* the_arr, int number_of_students) {
Then inside your function you are dynamically allocating memory which is stored inside the the_arr pointer which is not passed by reference therefore leading to the creation of a local pointer variable that will lose the pointer after its execution:
void operation(student*& the_arr [...]
I suggest you to avoid the below solution though and return the new pointer instead:
student* operation(student* the_arr, int number_of_students) {
delete[] the_arr;
the_arr = new student[3];
[...]
return the_arr; // <----
}
Allocating abc = new student[0]; doesn't make any sense. You are trying to allocate an array of 0 elements. Maybe you meant abc = new student[1];?
You should just use the vector or other sequence objects. Though I'm not sure what you are trying to do with your code. Here's a quick example:
// Vector represent a sequence which can change in size
vector<Student*> students;
// Create your student, I just filled in a bunch of crap for the
// sake of creating an example
Student * newStudent = new Student;
newStudent->a = 1;
newStudent->b = 2;
newStudent->name = "Guy McWhoever";
newStudent->status = 'A';
// and I pushed the student onto the vector
students.push_back( newStudent );
students.push_back( newStudent );
students.push_back( newStudent );
students.push_back( newStudent );

C++ Array on the heap

If I declare an array on the heap, how can I get information about the array?
Here is my code:
class Wheel
{
public:
Wheel() : pressure(32)
{
ptrSize = new int(30);
}
Wheel(int s, int p) : pressure(p)
{
ptrSize = new int(s);
}
~Wheel()
{
delete ptrSize;
}
void pump(int amount)
{
pressure += amount;
}
int getSize()
{
return *ptrSize;
}
int getPressure()
{
return pressure;
}
private:
int *ptrSize;
int pressure;
};
If I have the following:
Wheel *carWheels[4];
*carWheels = new Wheel[4];
cout << carWheels[0].getPressure();
How can I get call the .getPressure() method on any instance in the array when it is on the heap?
Also, if I want to create an array of Wheel on the heap, yet use this constructor when creating the array on the heap:
Wheel(int s, int p)
How do I do this?
Wheel *carWheels[4];
is an array of pointers to Wheel, so you need to initialize it with new:
for ( int i = 0; i < sizeof(carWheels)/sizeof(carWheels[0]); ++i)
carWheels[i]=new Wheel(); // or any other c-tor like Wheel(int s, int p)
later you can access it like that:
carWheels[0]->getPressure();
size of array can be retrieved like above:
sizeof(carWheels)/sizeof(carWheels[0])
[edit - some more details]
If you want to stick to array you will need to pass its size on function call because arrays decays to pointers then. You might want to stay with following syntax:
void func (Wheel* (arr&)[4]){}
which I hope is correct, because I never use it, but better switch to std::vector.
Also with bare pointers in arrays you must remember to delete them at some point, also arrays does not protect you against exceptions - if any will happen you will stay with memory leaks.
Simple, replace
Wheel *carWheels[4];
with
std::vector<Wheel*> carWheels(4);
for ( int i = 0 ; i < 4 ; i++ )
carWheels[i] = new Wheel(4);
You seem to be confusing () and [], I suggest you look into that.
You do know that ptrSize = new int(30); doesn't create an array, right?
Like C, you will need to lug the array's element count around with your allocation.
This information is actually stored by the implementation in some cases, but not in a way which is accessible to you.
In C++, we favor types such as std::vector and std::array.
Other notes:
ptrSize = new int(30); << creates one int with a value of 30
How do I do this?
Wheel(int s, int p)
Typically, you would just use assignment if you have an existing element:
wheelsArray[0] = Wheel(1, 2);
because you will face difficulty creating an array with a non-default constructor.
and while we're at it:
std::vector<Wheel> wheels(4, Wheel(1, 2));
is all that is needed to create 4 Wheels if you use vector -- no new required. no delete required. plus, vector knows its size.

Memory allocator causing mysterious pause

I should probably be sleeping. Instead, I'm coding. Specifically, I've written The World's Worse Memory Allocator(TM). It's got an array of bytes (chars) to use for memory for stuff; it's got a list of used memory blocks; it's got an index to allocate memory from. It even allocates memory. Deallocates, not so much.
That shouldn't be a problem, though, as to the best of my knowledge, nothing is new'd outside of the array and list classes and the destructor for those is called the proper number of times.
Edit: The problem is, the program enters what appears to be an infinite loop somewhere in the c++ back-end code itself, shortly after the MemoryManager's destructor is called. In fact, if the MemoryManager is put inside the Try-Catch block, the program never makes it outside the Try-Catch block. I need to know why and how to fix it, please, thanks.
This is the main loop which is doing terribly important allocations:
int _tmain(int argc, _TCHAR* argv[])
{
MemoryManager memoryManager = MemoryManager(1024);
try
{
int * n;
for (int t = 0; t < 32; ++t)
{
n = (int*)memoryManager.Allocate(4);
}
} catch (char* str) { std::cout << str; }
return 0;
}
And the MemoryManager, in all it's newbie glory:
// A memory manager
#pragma once
#include "stdafx.h"
#include "Array.h"
#include "SmartPointer.h"
class MemBlock
{
public:
unsigned int Start;
unsigned int End;
MemBlock() { Start = 0; End = 0; }
MemBlock(unsigned int start, unsigned int end)
{
Start = start; End = end;
}
~MemBlock() { }
};
class MemoryManager
{
private:
Array<char> memory;
List<MemBlock> memBlocks;
int index;
public:
MemoryManager(unsigned int size)
{
memory = Array<char>(size);
memBlocks = List<MemBlock>(size / 24);
index = 0;
}
~MemoryManager() { }
void* Allocate(unsigned int size)
{
memBlocks.Add(&MemBlock(index, index + size));
void* r = (void*)(memory.insecureAccess + index);
index += size;
return r;
}
};
Thanks.
You don't seem to have asked a question here, but I'm going to point out a horrible flaw in your approach anyway :)
If you are planning to write a Deallocate(void*) method then you are going to struggle.
You can match the void* pointer against your memBlocks list to determine which MemBlock it is, but you will only be able to reduce index if that MemBlock happens to be the last one returned by Allocate otherwise it is just a free hole in your array.
For a basic solution to this you would need a list of the free blocks and you would take allocated blocks from that list, and add them back to the list when they were deallocated.
This approach is called a free list: http://en.wikipedia.org/wiki/Free_list
Solved - Error in ignorance; it was an indirect error. I was using "delete theArray;" in the Array destructor (Array also being the base class of List) when I should have been using "delete [] theArray". The pause is now gone and the problem seems solved. Thanks for your time.