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).
Related
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".
This question already has answers here:
What and where are the stack and heap?
(31 answers)
Closed 8 years ago.
I am learning c++ and would like to know how a program like this is organized in primary-memory. I understand that there are a stack (with stackframes) and a heap. And I know that dynamically allocating something allocates it on the heap. This is done by operators like malloc or new. But I cant see them in this small c++ program.
The program consists of a main-class and a class named MyClass. This class has:
one constructor
one member variable (int)
one member-function
The main-class defines an object to Myclass and as well defines a pointer to this object.
SO - how are all this organized in memory?
#include <iostream>
using namespace std;
class MyClass {
int i;
public:
MyClass(int n) {
i = n;
}
int get_nmbr() {
return this->i;
}
};
int main() {
MyClass myClass(100), *p;
cout << myClass.get_nmbr() << endl;
p = &myClass;
cout << p;
return 0;
}
Let's go through this line by line.
int main() {
A new function starts with this line, and therewith a new scope.
MyClass myClass(100), *p;
Two things happen here. One, a variable myClass is declared within the function's scope, which makes it a local variable and thus it's allocated on the stack. The compiler will emit machine instructions that reserve enough space on the stack (usually by bumping the sp stack pointer register), and then a call to the class constructor executes. The this pointer passed to the constructor is the base of the stack allocation.
The second variable p is just a local pointer, and the compiler (depending on optimizations) may store this value on the local stack or in a register.
cout << myClass.get_nmbr() << endl;
Call the get_nmbr() method of the local myClass instance. Again, the this pointer points to the local stack frame allocation. This function finds the value of instance variable i and returns it to the caller. Note that, because the object is allocated on the stack frame, i lives on the stack frame as well.
p = &myClass;
Store the address of the myClass instance in variable p. This is a stack address.
cout << p;
return 0;
}
Print out the local variable p and return.
All of your code is only concerned with stack allocations. The result of that is that when the function's scope is left/closed at execution time (e.g. the function returns), the object will be automatically "destructed" and its memory freed. If there are pointers like p that you return from that function, you're looking at a dangling pointer, i.e. a pointer that points at an object that's freed and destructed. (The behavior of a memory access through such a dangling pointer is "undefined" as per language standard.)
If you want to allocate an object on the heap, and therefore expand its lifetime beyond the scope wherein it's declared, then you use the new operator in C++. Under the hood, new calls malloc and then calls an appropriate constructor.
You could extend your above example to something like the following:
{
MyClass stackObj(100); // Allocate an instance of MyClass on the function's stack frame
MyClass *heapObj = new MyClass(100); // Allocate an instance of MyClass from the process heap.
printf("stack = %p heap = %p\n", stackObj, heapObj);
// Scope closes, thus call the stackObj destructor, but no need to free stackObj memory as this is done automatically when the containing function returns.
delete heapObj; // Call heapObj destructor and free the heap allocation.
}
Note: You may want to take a look at placement new, and perhaps auto pointers and shared pointers in this context.
First things first. In C++ you should not use malloc.
In this program, all memory used is on the stack. Let's look at them one at a time:
MyClass myClass(100);
myClass is an automatic variable on the stack with a size equal to sizeof(MyClass);. This includes the member i.
MyClass *p;
p is an automatic variable on the stack which points to an instance of MyClass. Since it's not initialized it can point anywhere and should not be used. Its size is equal to sizeof(MyClass*); and it's probably (but not necessarily) placed on the stack immediately after myClass.
cout << myClass.get_nmbr() << endl;
MyClass::get_nmbr() returns a copy of the member i of the myClass instance. This copy is probably optimized away and therefore won't occupy any additional memory. If it did, it would be on the stack. The behavior of ostream& operator<< (int val); is implementation specific.
p = &myClass;
Here p is pointing to a valid MyClass instance, but since the instance already existed, nothing changes in the memory layout.
cout << p;
Outputs the address of myClass. Once again the behavior of operator<< is implementation specific.
This program (kind of) visualizes the layout of the automatic variables.
You have myClass object and pointer p (declared as MyClass *) created on stack. So. within myClass object the data members i also gets created on stack as part of myClass object. The pointer p is stored on stack, but you are not allocating for p, rather you are having p assigned to address of myClass object which is already stored on stack. So, no heap allocation here, at least from the program segment that you posted.
myClass is allocated on the stack. This program doesn't use heap exept maybe for allocating a stdout buffer behind the scenes. When myClass goes out of scope (e.g. when main returns or throws an exception), myClass is destructed and the stack is released, making p invalid.
In modern C++ it is considered safer to use smart pointers, such as the shared_ptr, instead of raw pointers.
To allocate myClass on the heap you could write:
#include <memory>
int main() {
std::shared_ptr<MyClass> p (new MyClass (100)); // Two heap allocations: for reference counter and for MyClass.
auto p2 = std::make_shared<MyClass> (101); // One heap allocation: reference counter and MyClass stored together.
return 0;
}
If I declare a struct such as this one:
struct MyStruct
{
int* nums;
};
MyStruct ms;
ms.nums = new int[4];
Do I need to call delete ms.nums; before exiting my program or will the member variable nums automatically get deallocated because the MyStruct instance ms wasn't declared on the heap?
Yes, you have to delete that.. struct's default destructor won't do that. It will just delete the pointer variable which holds the address of the object and object will be left alone forever.
Better to do the deletion inside the struct's destructor
struct MyStruct
{
int* nums;
public :
~MyStruct()
{
if(nums != NULL)
delete nums;
}
};
The member variable nums (which is a pointer) will get automatically deallocated when ms, the struct containing it, is popped off the stack.
However, the memory pointed to by nums will NOT. You should call delete [] ms.nums; before your program exits.
You always have to call delete to deallocate all the memory that you explicitly allocated using new.
When you allocate memory using new, memory is allocated in heap and the base address of the block is returned back.
Your struct is present in stack which contains a pointer pointing to that base address. When the struct object leaves the scope, the object is deallocated , i.e. the pointer containig the address of allocated heap memory block is gone, but the heap memory itself is still allocated which you can't deallocate now.
You need to call delete if memory allocated and pointer returned to num. Here num is a pointer inside a structure. Memory for num is allocated when you declare structure variable. But memory address which is allocated by new should be un-allocated by calling delete
Memory for the pointer itself will be deallocated when the object is destroyed, as it is for any class member. However, the array it points to won't be deleted - there is no way to know what the pointer points to, whether it was allocated by new or new[] or not dynamically allocated at all, or whether anything else still wants to use it. To avoid memory leaks, you should delete it, with the array form delete [] ms.nums;, once you've finished with it.
Since it's often hard to do this correctly, why not use a library class to manage the array correctly for you?
#include <vector>
struct MyStruct
{
std::vector<int> nums;
};
MyStruct ms;
ms.nums.resize(4);
Now all the memory will be released automatically when ms is destroyed; and the class is correctly copyable and (since C++11) efficiently movable.
The struct is allocated on the stack, which basically is a pointer to an Array. the array is allocated on the heap. Every time you write "new" that means that the allocation is on the heap therefore you need to "delete" it. On the other hand the struct will be remove as soon as you exit the function.
When program exit, OS will free all memory allocated by your program.
On the other hand, if a memory allocation occurs multiple times during the life of the program, then surely it should be released to prevent dangling pointers.
Hi i have few doubt related to heap variable...
I want to write a function as below ->
struct test
{
int x;
int y;
};
test* fun()
{
test *ptr = new test;
return ptr;
}
My doubt is returning a heap variable once it will go out of scope it will lost its value.
There is definitely a memory leak.(As heap variable is not deleted.)
So how can i design such kind of function.
Dynamically allocated objects (what you call heap variables) do not get destroyed at the end of the scope in which they were created. That's the whole point of dynamic allocation. While the test object is dynamically allocated, the pointer ptr is not - it will be destroyed when it goes out of scope. But that's okay! You copy the value of the pointer out of the function and this copy still points at the test object. The test object is still there. The function you've written is fine, but it isn't exactly good style.
Yes, there is a memory leak if nobody ever does delete on a pointer to the test object you created. That's a problem with returning raw pointers like this. You have to trust the caller to delete the object you're creating:
void caller()
{
test* p = fun();
// Caller must remember to do this:
delete p;
}
A common C-style way of doing this (which is definitely not recommended in C++) is to have a create_test and destroy_test pair of functions. This still puts the same responsibility on the caller:
void caller()
{
test* p = create_test();
// Caller must remember to do this:
destroy_test(p);
}
The best way to get around this is to not use dynamic allocation. Just create a test object on the stack and copy it (or move it) out of the function:
test fun()
{
test t;
return t;
}
If you need dynamic allocation, then you should use a smart pointer. Specifically, the unique_ptr type is what you want here:
std::unique_ptr<test> fun()
{
return std::unique_ptr<test>(new test());
}
The calling function can then handle the unique_ptr without having to worry about doing delete on it. When the unique_ptr goes out of scope, it will automatically delete the test object you created. The caller can however pass it elsewhere if it wants some other function to have the object.
You are not returning a heap variable, you are returning a value of a stack variable that holds a pointer to the heap. The stack variable goes out of scope; the memory pointed to by the pointer is in the heap - it never goes out of scope.
There will be a memory leak unless you release the memory in the caller.
My doubt is [that] returning a heap variable once it will go out of scope it will lo[se] its value.
No worry, because since you're returing the pointer by value; so the pointer will go out of scope, but since you're returning the memory that it points to, there is no memory leak (only if we can rely on the caller to delete it).
However, if we had returned the pointer by reference then we would have a problem:
test*& fun() // note the & (reference)
{
test *ptr = new test;
return ptr;
}
Here you're returning a reference to a temporary. When the variable goes out of scope you will be using an object that doesn't exist. This is why you can't return temporaries by reference.
My doubt is returning a heap variable once it will go out of scope it will lost its value.
No heap variable does not go out of scope as do go stack variables...
There is definitely a memory leak.(As heap variable is not deleted.)
Yes we have to free memory allocated on heap by ourself, otherwise there is memory leak...
I would suggest to read some tutorial related to it.
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.