Do functions clear dynamic memory upon exiting scope? - c++

In C++, how does a function treat memory that has been dynamically allocated upon exiting the scope of the function? Is this memory cleared, or can it be passed back into the main block?
In context: I have a function, and I pass it a pointer to double to serve as an array. I dynamically allocate this memory within the function, initialise the elements and the exit the function.
void my_func(double* ptr){
ptr = new double[2];
ptr[0] = 15; ptr[1] = 10;
}
In the main block, I then use the newly allocated array.
int main(){
double* ptr;
my_func(ptr);
cout << ptr[0] + ptr[1] << endl;
delete[] ptr;
return 0;
Will this work? Are there dangers/pitfalls associated with this approach?

In C++, how does a function treat memory that has been dynamically allocated upon exiting the scope of the function? Is this memory cleared, or can it be passed back into the main block?
In C++, memory that has been manually (dynamically) allocated has to be manually deallocated.
In context: I have a function, and I pass it a pointer to double to serve as an array. I dynamically allocate this memory within the function, initialise the elements and the exit the function.
You are taking the pointer by value, so while you can change the contents of what the pointer points to you cannot change the pointer itself. Doing so changes only the local copy of the pointer. If you take the pointer by reference, then it would work:
void my_func(double*& ptr)
{
ptr = new double[2];
ptr[0] = 15; ptr[1] = 10;
}
Will this work? Are there dangers/pitfalls associated with this approach?
It will mostly work, but its not the way to go in C++ because of the associated pitfalls. Better go with a vector:
std::vector<int> my_func()
{
std::vector<int> buffer;
buffer.push_back(15);
buffer.push_back(10);
return buffer;
}

Will this work? Are there dangers/pitfalls associated with this approach?
It may work as long as nothing goes wrong. If an exception gets thrown, it'll generally leak memory. To avoid that, you generally want to free the memory in the destructor of some class, then create an instance of that class with automatic storage duration. That means it'll be destroyed when it goes out of scope, and will (in turn) release the memory it's controlling.
The standard library already has a variety of containers to do that. What you have is closest to a std::vector, but there are also std::deque, std::list etc.

Related

Live on heap or stack when use new operator within a function block?

For instance:
void Func()
{
int* i = new int; // the simplest case
vector<int*> v = new vector<int*>; // another case, not sure if **new** is using correctly here
vector<int*>* vPointer = new vector<int*>;
}
void main()
{
Func();
}
So, if I allocate dynamic memory(by using new operator) for local variables in functions,
Do they live on heap or stack?
when the program exits the function, are they still dangling around on heap or destroyed as function variables?
Can I use new operator on non-pointer types? How to delete (or return back the allocated heap memory) it later?
Thank you!
int i = 3;
this creates an object of type int on the stack. (The C++ standard uses the term "automatic storage", and I'm usually a stickler for proper use of formal terms, but "stack" and "heap" are deeply embedded in programming vocabulary, so "stack" and "heap" are just fine as technical terms).
int *ip = 0;
this creates an object of type int* on the stack. ip holds a null pointer.
int *ip = new int;
this creates an object of type int* on the stack, just like the previous one. It holds a pointer to memory on the heap (see earlier parenthetical; the formal term is "free store"). You know that the memory is on the heap because that's what operator new does.
When you're finished with the heap memory you have to release it:
delete ip;
if you don't delete it and the function that created it returns, the local variable (ip) that held the pointer is gone. The memory has been allocated and it hasn't been freed, so unless you copied the pointer to some place else, you have no way to get at the memory you allocated. That's called a "memory leak".

C++ Containers of pointers

I have been pondering an issue today and it's difficult to find the answer on google.
I'm trying to understand the STL container behaviour when dealing with pointers to both objects allocated on the heap, and on the stack.
So, start with objects, no pointers ... imagine I have ...
std::vector<int> myVec;
while(true)
{
int myInt = 5;
myVec.push_back(myInt);
myVec.pop_back();
}
My understanding is that the pop_back() method will ensure the integers contained in the vector are deleted, not just removed from the container. So if this ran and did a billion iterations, I should not expect to leak memory. Everything I insert, will be deleted. A memory check shows this behaviour.
Now consider I use a vector of pointers (to objects on the heap) ...
std::vector<int*> myVec;
while(true)
{
int * myIntP = new int(5);
myVec.push_back(myIntP);
myVec.pop_back();
}
In this case, only the pointer itself ought to be removed each time pop_back() is called, and the underlying object remains un-deleted, causing a memory leak. So after a billion iterations I have quite some significant memory being used, even though I have no entries in my vector.
Now what if I have a vector of pointers (to objects on the stack) ...
std::vector<int*> myVec;
while(true)
{
int myInt = 5;
int * myIntP = &myInt;
myVec.push_back(myIntP);
myVec.pop_back();
}
Here the pointers point to stack objects. Is their memory freed in the call to pop_back(), or not? A memory check showed me that this behaviour was no memory leaked. The small amount of memory used, indicated that this behaved like objects on the stack. However this was not expected to me, because if the pointer had been passed into me from another function, to a stack variable i.e.
void myFunc(int * myIntP)
{
std::vector<int*> myVec;
myVec.push_back(myIntP);
myVec.pop_back();
}
int main()
{
int myInt = 5;
int * myIntP = &myInt;
myFunc(myIntP);
std::cout << (*myIntP) << std::endl;
return 0;
}
Then allowing the vector to free this memory, would render my myIntP pointing to removed data. So surely this can't be correct?
Could anyone help explain?
Also is there a name for "a pointer pointing to a variable on the stack" i.e. not initialised with "new"?
Thanks
Joey
while(true)
{
int myInt = 5;
int * myIntP = &myInt;
myVec.push_back(myIntP);
myVec.pop_back();
}
You only actually have one int here, myInt with a value of 5. The loop will re-use the same one. You push a pointer to that one int into the vector and then remove it. Nothing else is happening. There isn't a memory leak because you are not allocating new ints.
STD containers do nothing different for pointers than they would for a 32/64 bit interger. As far as they care, a pointer is just another number. So, if you insert a pointer into a container, it is your responsibility to delete it.
If you make a pointer to a variable on the stack, the variable will be destructed when it goes out of scope, regardless of the pointer. And destructing the pointer (as long as you don't call delete on it) will have no effect on the variable.
So if you stop using your pointer before, no problem, if you store it longer, problem...
And if you plan on using pointers on dynamically allocated variable, you should look into smart pointers.
Here the pointers point to stack objects. Is their memory freed in the call to pop_back(), or not?
No, they are not. They are freed when they go out of scope, which happens at the }. After the }, the memory is no longer used for this variable (the stack-frame popped off) and will be reused! So if you didn't pop-off the pointer right after pushing it, your vector would contain a dangling pointer when the variable goes out of scope.
So, let's go through each of your examples:
std::vector<int> myVec;
while(true)
{
int myInt = 5;
myVec.push_back(myInt);
myVec.pop_back();
}
The push_back() method makes a copy of the argument and stores the copy internally. So, if you were storing an stack-allocated object instead of a primitive, a copy constructor would have been called. The pop_back() method does not assume anything either. It removes the copy of the item you stored (whether it was a value or a pointer) and removes it from its internal storage. If the copy stored was a stack-allocated object, the class' destructor will be called when the container manages its internal memory because the copy item will no longer be in scope.
Your second example:
std::vector<int*> myVec;
while(true)
{
int * myIntP = new int(5);
myVec.push_back(myIntP);
myVec.pop_back();
}
As you stated, the integer is allocated on the heap. Calling push_back() still stores the argument. In this case, you are not storing the value of the integer "5", the value of the pointer, an address of a memory location that contains the value of "5". Since you allocated the memory that stores the "5", you are responsible for getting that pointer and deallocate the memory. The pop_back() method does not delete the pointer for you nor returns you a copy of the pointer.
Your third example has subtle differences:
std::vector<int*> myVec;
while(true)
{
int myInt = 5;
int * myIntP = &myInt;
myVec.push_back(myIntP);
myVec.pop_back();
}
In this case, you are not allocating any memory on the heap. You assigning the address of myInt, which is a stack-allocated value, to a pointer. Stack memory lives through out the life of a process and does not deallocate on its own. However, once you leave the current scope (the while loop), the memory reused by something else. The memory is still there, but it may no longer have the value you expect.
Your last example:
void myFunc(int * myIntP)
{
std::vector<int*> myVec;
myVec.push_back(myIntP);
myVec.pop_back();
}
int main()
{
int myInt = 5;
int * myIntP = &myInt;
myFunc(myIntP);
std::cout << (*myIntP) << std::endl;
return 0;
}
You were expected the memory for myInt to be dealloated after making myFunc() was called. However, container methods do not modify the supplied values. They copy them. When myFunc() pushed the myIntP pointer, it is pushing the pointer, the address of what myIntP points to, not the value in memory of that address. You would have to dereference the pointer, using call:
myVec.push_back(*myIntP);
Note that even if you did this, containers copy the value. So, myInt is still unaffected.
You are confusing and conflating "destruction" and "deletion" -- they are NOT the same thing, but are two different concepts in C++.
Deletion can only happen with pointers -- if you try to delete a non-pointer, you'll get a compile-time error. Deletion first destroys the pointed at object and then returns the memory for it to the heap.
Destruction on the other hand can happen with anything, but is mostly only of interest with classes, where it calls the destructor. With any type that has no destructor (such as int or any raw pointer type), destruction does nothing. While you CAN destroy an object manually, you pretty much never do -- it happens automatically for you when something else happens. For example, when a local variable goes out of scope, it is destroyed.
So in your code above, what happens? Well you have a local std::vector which is destroyed when it goes out of scope. Its destructor will delete anything it allocated internally, and destroy all the elements of the vector. It will NOT however, delete any elements of the vector. When you have vector<int>, that's all there is, since nothing else was allocated, but when you have a vector<int *>, if those pointers were allocated, they'll leak. If they weren't allocated (if they point at locals), there's nothing to leak.
I think you need to learn deep the scope variable validity
exemple :
{
int myVar;//Construct myVar on the stack
}//At this point, myVar is deleted with the stack
in your last exemple, you declare myInt at the start of main and don't do anything on value in myFunc.
It's normal to don't lose myInt data. it will be erase after the return 0;

Pointers assigned inside an invoked function valid?

I want to understand whether in this piece of code, pointers stored in the vector by func() are valid when accessed from main_func(), and if so why?
void func(vector<double*>& avector) {
double a=0,b=0;
for (int i=0;i<10;i++) {
double *a = new double[2];
avector.push_back(a);
avector[avector.size()-1][0] = a;
avector[avector.size()-1][1] = b;
}
}
void main_func(){
vector<double*> v;
func(v);
for (int i=0;i<v.size();i++)
{
// access a
// References stored in vector valid???
}
}
Why don't you use a vector of pair vector<pair<double,double>>
http://www.cplusplus.com/reference/utility/pair/
Let's get to basics. A pointer is simply four-byte integer value denoting address in memory in which some data exists. Dynamic memory allocation is application-global, so if you allocate memory anywhere in your program by new, new[] or malloc (or something like this), you can use this memory anywhere you like and OS guarantees, that it won't be moved anywhere (in terms of address, that you got from the memory allocation routine).
So let's get back to your program. You allocate some memory inside the function and store the addresses of pointers to that memory in the vector. When you exit that function, these pointers are still completely valid and you can use them as you wish.
Don't forget to free them, when you don't need them anymore!
They are valid because you created them with new and that means they have dynamic storage duration. You do however lack the corresponding delete and therefore have a memory leak.
Your vector does not store references, but pointers to objects on the heap. That object is an array of two doubles, and you just copy the values from your local variable. So everything is alright (except that you don't release the memory).
If you somewhere (store and) return references or pointers to function locals, those won't have any meaning outside the function.

C++ filling an array with numbers then returning a pointer to it

Ive been faced with a problem recently that I can't think of a good way to solve. I'm using a case structure to attempt to set attributes to a "character" that will be passed to an object constructor.
Example:
//note this is inside a function with a return type of int*
int selection;
cin >> selection;
int * iPtr;
switch(selection){
case 1:{
int anArray[6] = {8,5,2,4,250,100} // str, dex, int, luck, hp, mp
iPtr = anArray;
return iPtr;
}
//more cases and such below
The issue that I'm having is that when I return my pointer it seems to be filled with a good amount of junk, rather than the information, rather than the information that I would be expecting it to hold. Is that because the array gets destroyed at the end of the scope? If so what should I do to make this work out how I'm hoping for it to (getting a pointer with the values that I want).
Thanks!
Yes - anArray is declared on the stack. When the function exits, its stack frame is reclaimed, so it's no longer valid to refer to that memory. If you want the array to persist, allocate it on the heap instead:
int* anArray = new int[6]; // and initialize
return anArray;
Just remember to clean it up later at some point with the corresonding delete[].
EDIT
You should prefer to use something that automatically manages resources for you, like in Praetorian's answer, so that you don't accidentally leak memory.
Yes, the array you've declared is indeed local to the function and no longer exists once the function exits. You can dynamically allocate an array using new and then have the caller delete[] the memory (but don't do this!), or modify your function to return an std::unique_ptr instead of a raw pointer.
unique_ptr<int[]> anArray (new int[6]);
// do initialization
return anArray;
Now, the caller doesn't have to worry about freeing memory allocated by the function.
EDIT:
There are a couple of different ways to perform initialization of the unique_ptr.
anArray[0] = 8;
anArray[1] = 5;
// etc ...
OR
int init[6] = {8,5,2,4,250,100};
std::copy( &init[0], &init[0] + 6, &anArray[0] );
Yes, it's because the local array is overwritten as the program runs. You can either declare the array static in the method (which would be a good idea for a fixed array like this), declare it at global scope, or allocate an array with new to return. The last alternative gives you the opportunity to have a different array returned for each call, but remember to deallocate the arrays after use.
In C++, the best answer is not to return a pointer. Instead, use a proper object instead of a C array or manually allocated memory and return this object:
std::vector<int> f() {
std::vector<int> array;
// fill array
return array;
}
Using new int[x] (or whatever) is really, really deprecated in modern C++ code and is only deemed acceptable under very special circumstances. If you use it in normal code, this is a very obvious place for improvement. The same goes for other uses of manually managed memory. The whole strength of C++ lies in the fact that you don’t have to manage your own memory, thus avoiding a multitude of hard to track bugs.
Yes, it is because the array you created is created on the stack, and when you return, the part of the stack that you were at is overwritten (presumably by a debug process).
To avoid this, you would write
int* anArray = new int[6];
// fill the array
return anArray;
In this case, you will also have to delete the returned result when you are finished with it, such as in
int* dataArray = getTheArray();
// Use the dataArray
delete [] dataArray;
Allocate array on the heap
int* anArray = new int[6];
You will have to delete it manually:
delete[] iPtr;

memory questions, new and free etc. (C++)

I have a few questions regarding memory handling in C++.
What's the different with Mystruct *s = new Mystruct and Mystruct s? What happens in the memory?
Looking at this code:
struct MyStruct{
int i;
float f;
};
MyStruct *create(){
MyStruct tmp;
tmp.i = 1337;
tmp.j = .5f;
return &tmp;
}
int main(){
MyStruct *s = create();
cout << s->i;
return 0;
}
When is MyStruct tmp free'd?
Why doesn't MyStruct tmp get automatically free'd in the end of create()?
Thank you!
When you use the new keyword to get a pointer, your struct is allocated on the heap which ensures it will persist for the lifetime of your application (or until it's deleted).
When you don't, the struct is allocated on the stack and will be destroyed when the scope it was allocated in terminates.
My understanding of your example (please don't hesitate to inform me if I'm wrong, anyone):
tmp will indeed be "freed" (not the best word choice for a stack variable) at the end of the function since it was allocated on the stack and that stack frame has been lost. The pointer/memory address you return does not have any meaning anymore, and if the code works, you basically just got lucky (nothing has overwritten the old data yet).
For question 1, you are looking at the heap memory and the stack memory. In short,
Mystruct S;
creates S on the stack. When S goes out of scope, it will be destroyed. Hence if S is inside a function, when the function returns, S is destroyed.
Whereas
MyStruct *S = new MyStruct();
Is on the heap. It is a block of memory set aside for programs to store variables in, and S will store a pointer to the start memory block of the new MyStruct. It will always be within the heap until you free it; if you do not free it when your program ends, you get the nefarious memory leak.
On to question 2 - the local MyStruct is destroyed upon the function exiting; the MyStruct pointer which points to its return value is pointing to undefined region. It may still work, because the OS has not yet reclaimed the memory, but it is definitely not correct behavior - or a safe thing to do.
First:
Mystruct* s = new Mystruct;
The new Mystryct part allocates memory on the heap for an object of that type. In C++ it will also execute the default constructor of the type. The Mystruct* s part declares a pointer variable that points to the address of the first byte of the newly allocated object memory.
Second:
Mystruct s;
It'll do the same as the first with two differences, which can be simplified as: The allocated memory for the object is on the stack and there's no pointer variable pointing to the memory, instead s is that object. The address of to that object is &s, so a pointer that points at the object s shall be assigned the value &s.
Why doesn't MyStruct tmp get automatically free'd in the end of create()?
It does. The tmp destructor runs after the return statement, so the address returned by the function will be to a memory that will soon be overwritten by something else, which at best will cause a segmentation fault (or the equivalent) and at worst corrupt your data.
Both of your questions deal with storage duration and scope.
First, when you dynamically allocate an object, the object and a pointer to it is valid until you free it. If it is an automatic variable (i.e., not dynamically allocated by new, malloc, etc., and not declared static), the variable goes out of scope as soon as the object's scope ends (usually that's the } at the same "level" as the one in which the object was defined). It also has "automatic storage duration", which means that the storage for it also goes away when the object is not in scope.
For your second question, tmp has a scope that ends with the ending } of create. It also has the same storage duration. A pointer to tmp is only valid within that storage duration. Once create() exits, the pointer to tmp becomes invalid, and cannot be used.
Mystruct *s = new Mystruct;
Dynamically allocates s on the heap. It will not be automatically freed. (Also, s is a pointer, not directly a Mystruct).
Mystruct s;
Statically allocates s on the stack. It will be "freed" when it goes out of scope.*
Your code is invalid. When you refer to tmp outside of create, you are using a wild pointer to access dead memory. This results in undefined behavior.
Pretty much. Using it out of scope is undefined behavior, even if the value is still in memory.
Q1:
Mystruct *s = new Mystryct;
Creates the structure variable on the heap, which is being pointed by variable s.
Mystruct s;
Here the structure is created on the stack.
Q2:
MyStruct *create(){ MyStruct tmp; tmp.i = 1337; return &tmp; }
is wrong!! You are creating a local struct variable on stack which vanishes when the function return and any reference to it will be invalid. You should dynamically allocate the variable and will have to manually deallocate it later say in main.
In Mystruct *s = new Mystruct there is static variable, pointer, that is allocated in the start of the function call on the stack. When this line is running, it's allocating on the heap the struct. In Mystruct s it allocates the struct on the stack, "staticly" when the function runs (the constructor, if any, will run in the decleration line).
"Why doesn't MyStruct tmp get automatically free'd in the end of create()?" - well, it is. But, the memory still exist, so you can access it and it may contain the old values.
Mystruct *s = new Mystryct allocates on heap.
One needs to explicitly delete it.
Whereas Mystruct s allocates the structure on stack.
It automatically gets freed as the stack unwinds (Variable goes out of scope)
so for Case 2, the tmp will be freed as soon as create() exits. So what you'll have returned is a dangling pointer which is very dangerous.
If it's too difficult, follow this rule of thumb,
For every new operator called, delete must be called in the end.
For every new[] operator called, delete[] must be called in the end.
use smart pointers which automatically delete the memory allocated instead of normal pointers.
If you're returning objects from a function like in create, make sure you're allocating it using the new operator and not on stack like you've done in the example. Make sure that the caller calls delete on the pointer once he finishes with it.
struct MyStruct{ int i; };
MyStruct create(){ MyStruct tmp; tmp.i = 1337; return tmp; }
int main(){
MyStruct s = create();
cout << s.i;
return 0;
}
or
struct MyStruct{ int i; };
MyStruct* create(){ MyStruct* tmp = new MyStruct; tmp->i = 1337; return tmp; }
int main(){
MyStruct* s = create();
cout << s->i;
delete s;
return 0;
}
would work. Because the copy constructor would create a copy of the struct when it is assigned to s in the first case.
The whole new/delete stuff (dynamic memory allocation) belongs to the basics of C++. You do not have to use any new or delete to implement basic algorithms. Copy constructor and so on will always do the job and make the code easier to understand.
If you want to use new you should also read about autopointer and so on. There is no garbage collection of memory in C++.
I think Thinking C++ explains the concepts of dynamic memory very well(chapter 13).