Consider the following code snippet:
#include <vector>
using namespace std;
void sub(vector<int>& vec) {
vec.push_back(5);
}
int main() {
vector<int> vec(4,0);
sub(vec);
return 0;
}
Assuming "vec" has no space left to store the 5 in the "sub" function, where does it allocate new memory?
In the stack frame of the sub function? In that case the 5 would be deleted at the end of the sub function. But the stack frame of the main function can't grow, as the stack frame of the sub function lies on top of the stack at that moment.
Does a std::vector allocate memory for its elements on the heap?
But how does it free that heap memory?
If it's a local vector on the stack, the stack frame of a function including the vector is deleted in the end without signaling the vector that it will be deleted?
Does a std::vector allocate memory for its elements on the heap?
Yes. Or more accurately it allocates based on the allocator you pass in at construction. You didn't specify one, so you get the default allocator. By default, this will be the heap.
But how does it free that heap memory?
Through its destructor when it goes out of scope. (Note that a pointer to a vector going out of scope won't trigger the destructor). But if you had passed by value to sub you'd construct (and later destruct) a new copy. 5 would then get pushed back onto that copy, the copy would be cleaned up, and the vector in main would be untouched.
All containers in the STL are parameterized with template arguments, usually the last argument is called A or Allocator and defaults to std::allocator<...> where ... represents the type of the value stored within the container.
The Allocator is a class that is used to provide memory and build/destroy the elements in this memory area. It can allocate memory from a pool or directly from the heap, whichever you build the allocator from. By default the std::allocator<T> is a simple wrapper around ::operator new and will thus allocate memory on the heap as you inferred.
The memory is allocated on demand, and is deallocated at the very least when the vector's destructor is called. C++11 introduces shrink_to_fit to release memory sooner too. Finally, when the vector outgrow its current capacity, a new (larger) allocation is made, the objects are moved to it, and the old allocation is released.
As will all local variables, the destructor is called when executed reaches the end of the scope it has been declared into. So, before the function is exited, the vector destructor is called, and only afterward does the stack shrinks and control returns to the caller.
Also note that your vector (vec) is object itself. It resides on the stack and when this object goes out of scope (which is end of main in your case), it is destructed. Memory for elements is allocated during initialization of this object and released with its destruction, which is a lovely example of RAII idiom, since the resource management of elements is tied to the lifespan of vector object.
Because you gave sub the adress of the vector in the heap, it will allocate in the heap. If there's no space left, exception should be thrown.
Related
In The C++ Programming Language, there is the following example (section
3.2.4).
unique_ptr<Shape> read_shape(istream& is);
void user()
{
vector<unique_ptr<Shape>> v;
while (cin)
v.push_back(read_shape(cin));
draw_all(v);
// call draw() for each element
rotate_all(v,45);
// call rotate(45) for each element
} // all Shapes implicitly destroyed
Stroustrup is trying to make the point that by using unique_ptrs, one
doesn't have to manually loop through the vector and delete all
Shapes. I'm having trouble understanding why this is true.
The way I understand smart pointers is that if a smart pointer sptr is
allocated on the stack, with something like
std::unique_ptr<Shape> sptr(new Shape());
you don't need to call delete on it at the end of the function. However,
from what I can tell in the above example those smart pointers are not
on the stack, they're put inside the data array of v, which is on the
heap.
Whether the unique_ptr is on the stack or the heap doesn't really matter. What matters is that it will automatically call delete on the target pointer when its destructor runs.
When the vector goes out of scope, the vector's destructor runs. That destroys all contained elements (calling their destructors in the process) and then deallocates its heap buffer.
This is what destructors are for. You don't see the "manual loop" that destroys the unique pointers because that loop is within the destructor of the vector. All containers destroy their elements.
When the destructor for std::vector runs it calls the destructor for each object it contains. The destructor for std::unique_ptr calls delete/delete[] on the pointer it wraps, so all of the memory that was allocated will be cleaned up correctly.
When a std::unique_ptr itself is destructed or reset, it calls delete or delete[] (or a custom deleter that you specify) on the object/array that it is currently holding a pointer to.
If the std::unique_ptr is created in automatic memory, such as the stack, it is destructed when it goes out of scope.
If the std::unique_ptr is created in dynamic memory, such as the heap, it is destructed when delete is called on it.
A container owns the elements that it stores. It knows whether its elements are of a type that defines a destructor or not, and if so then it will call that destructor on each element when needed, such as when removing individual elements from the container, or when the container itself is destructed or cleared.
So, if you have a container of std::unique_ptr elements, they will be destructed for you when appropriate, which in turn will destruct the things that they are pointing at.
Yes, if you create something on the heap, you have to delete it yourself. Unlike automatic variables (those on the stack, even though the standard doesn't actually mandate the existence of a stack), the lifetime (scope) of those objects can continue across function return boundaries.
However, the vector here is not on the heap - it's actually an automatic variable that will undoubtedly store some of its information on the heap (the array holding the vector elements, most likely), but the variable itself is not.
That means, when it goes out of scope on exit from user(), the destructor is called for it. That destructor is smart enough to free the heap-specific stuff for the vector itself, and call the destructor for each element in the vector.
And, of course, destructing each of those elements may cause further destructors to be called. If one of those elements being destructed is a smart pointer, it will know that it needs to release its hold on the underlying pointer, by either freeing it or decrementing a count to say it has no further interest in it.
creating a vector:
std::vector<int> pqrs;
delete in proper way to free up all memory (prevent memory leaks and other memory related issues) inside the function:
pqrs.clear();
std::vector<int>().swap(pqrs);
My question is: both clear and swap required (say for calling destructor)? or swap is sufficient for all purpose.
In case of std::vector<int> you don't need to do either clear() nor swap to free memory, because elements of std::vector<int> here (ints) are automtically allocated and freed by the std::vector<int> methods anddestructor. Data will be freed at the end of scope (function or program).
Hence,answer to your question would be, You don't need to call clear or swap.
Since vector<int> object in above question is a variable with automatic storage - so it will be automatically destroyed when it goes out of scope. And when a container object goes out of scope, it's destructor is called which in-turn frees up space used for storage of contained elements and during this step destructor for all contained elements also gets invoked (in case of user-defined types). So, if we have just plan int elements, no need to do anything extra. But we would have memory leak if contained type if T* where T is some user-defined type because in that case destructor wouldn't be called explicitly for pointed-to objects.
Your phrase about memory leaks makes the whole meaning of the question unclear. When the vector goes out of scope, the memory is released. There should be no memory leak.
In major projects, it is fairly common to need a vector to release its allocation at a certain point before it goes out of scope. Failure to do so is not a memory leak but may be a problem. For that purpose, .clear() is useless. The swap approach you suggested (without the .clear) works. I don't know a way to do it without swap.
We have a scenario where we need to create an
std::vector<std::vector<float>> data;
because the vectors aren't at all the same length.
When data gets freed, does every vector inside data also free up its space?
All of the standard library types implement RAII appropriately. That is, any kind of internal dynamic allocation that they perform will be cleaned up automatically by the time the object is destroyed. You never need to worry about it.
In the case of the standard containers, like std::vector, it will automatically ensure that each of its elements is destroyed. Of course, if the elements of the std::vector are themselves std::vectors, they will in turn destroy their elements. Everything is automatic.
You may have seen examples in which you have a std::vector<T*> and the T objects were then allocated manually using new. It's important to realise here that the elements of the vector are not the T objects, but T* objects. The pointers will be cleaned up automatically. Since you manually allocated the T objects, you need to manually deallocate them. (As #Veritas says in the comments, in this case you should prefer using smart pointers)
Yes
Whenever The "Scope" of 'data' ends , The destructor will be automatically called and memory that was allocated for'data' will be freed.
Whenever the destructor is called for a vector then the destructor each of its elements will be called.
Suppose for vector a(5)
Here destructors of a[0],a[1],... will be called.
Similarly in the above case vector< vector > x;
destructors of x[0],x[1] will be called consecutively..
But here each element x[i] is again a vector so again destructors of x[i][0],x[i][1]... will be called..
In this way all elements are destroyed Recursively..
I'm writing a stack based allocator for STL. The idea is to allocate a big chunk of memory once and let it build up while objects are constructed and then reset it to zero when needed. For example, this could be used for storing level information for a game or for objects that are created for a single iteration of a game loop. When you load a level you build up the stack, when you need to load a new a level you just reset the top pointer to the beginning, no OS calls needed.
Now my issue is the way the standard allocator does things, namely the deallocate() function. In this article i can read that
In the default allocator, the block of storage is deallocated using
::operator delete.
which implies that by using the deallocate() function both the memory is freed and the destructor is called. Now for the purpouse of my allocator i can make the deallocate() function to be empty, since i'm not going to deallocate memory for individual objects.
So, the question is, how do the STL containers use the allocator class to create new objects? Since the default allocator uses new and delete, do the containers ever call construct() or destroy()? Should i make my deallocate() function also call the descrutor?
I guess the same question goes for the allocate() and construct() methods.
which implies that by using the deallocate() function both the memory
is freed and the destructor is called
No it doesn't. ::operator delete is the global delete function, it just frees the memory. The delete operator is a different thing, despite the similarity of name -- it destructs and then calls a delete function (either the global delete function or an overload).
The destructor is called by the destroy function of the allocator.
Standard containers use allocate to get some memory, then construct if and when they need that memory to contain an element, destroy if and only if they constructed, and deallocate to free the memory. For example:
{
std::vector<int> v; // may or may not call anything on the allocator
v.reserve(10000); // calls 'allocate'
v.resize(100); // calls 'construct' 100 times
v.resize(50); // calls 'destroy' 50 times
} // destructor calls 'destroy' 50 times and then 'deallocate'
Suppose I have a class named A:
Class A
{
...
}
And what's the difference between the following 2 approaches to instanciate an object:
void main(void)
{
A a; // 1
A *pa=new A(); // 2
}
As my current understanding (not sure about this yet):
Approach 1 allocate the object a on the stack frame of the main() method, and so this object cannot deleted because that deletion doesn't make sense (don't know why yet, could someone explain that?).
Approach 2 allocate the object a on the heap of the process and also a A* vairable pa on the stack frame of the main() method, so the object can be deleted and and the pa can be assigned null after the deletion.
Am I right? If my understanding is correct, could someone tell me why i cannot delete the a object from the stack in approach 1?
Many thanks...
Object a has automatic storage duration so it will be deleted automatically at the end of the scope in which it is defined. It doesn't make sense to attempt to delete it manually. Manually deletion is only required for objects with dynamic storage duration such as *pa which has been allocated using new.
The objects live time is limited to
the scope the variable is defined
in, once you leave the scope the
object will be cleaned up. In c++ a
scope is defined by any Block
between { an the corresponding }.
Here only the pointer is on the stack and not the object, so when
you leave the scope only the pointer
will be cleaned up, the object will
still be around somewhere.
To the part of deleting an object, delete not only calls the destructor of your object but also releases its memory, this would not work as the memory management of the stack is automated by the compiler, in contrast the heap is not automated and requires calls to new and delete to manage the live time of an object.
Any object created by a call to new has to be deleted once, forgetting to do this results in an memory leak as the objects memory will never be released.
Approach 1 declared a variable and created an object. In Approach 2, you created an instance and pointer to it.
EDIT : In approach 1, the object will go out of scope and will be automatically deleted. In approach 2, the pointer will be automatically deleted, but not what it is pointing to. That will be your job.
Imagine stack as void* stack = malloc(1.000.000);
Now, this memory block is managed internally by the compiler and the CPU.
It is a shared piece of memory. Every function can use it to store temporary objects there.
That's called automatic storage. You cannot delete parts of that memory because its purpose is
to be used again again. If you explicitly delete memory, that memory returns back to the system,
and you don't want that to happen in a shared memory.
In a way, automatic objects are also get deleted. When an object gets out of scope the compiler places
an invisible call to object's destructor and the memory is available again.
You cannot delete objects on the stack because it's implemented in memory exactly that way -- as a stack. As you create objects on the stack, they are added on top of each other. As the objects leave scope, they are destroyed from the top, in the opposite order they were created in (add to the top of the stack, and remove from the top of the stack). Trying to call delete on something in the stack would break that order. The analogy would be like trying to pull some paper out of the middle of a stack of papers.
The compiler controls how objects are created and removed on the stack. It can do this because it knows exactly how large each object on the stack is. Since the stack size is set at compile time, it means that allocating memory for things on the stack is extremely fast, much faster than allocating memory from the heap, which is controlled by the operating system.
Allocation does two things:
1) Allocates memory for the object
2) Calls the constructor on the allocated memory
Deletion does two things:
1) Calls the destructor on the object
2) Deallocates the memory used by the destructed object
When you allocate on the stack (A a;), you're telling the compiler "please make an object for me, by allocating memory, then call the constructor on that memory. And while you're at it, could you handle calling the destructor and freeing the memory, when it goes out of scope? Thanks!". Once the function (main) ends, the object goes out of scope, the destructor is called, and the memory is freed.
When you allocate on the heap (A* pa = new A();), you're telling the compiler "please make an object for me. I know what I'm doing, so don't bother calling the destructor or freeing the memory. I'll tell you when to do it, some other time". Once the function (main) ends, the object you allocated stays in scope, and is not destructed or freed. Hopefully you have a pointer to it stored somewhere else in your program (as in, you copied pa to some other variable with a bigger scope). You're gonna have to tell the compiler to destruct the object and free the memory at some point in the future. Otherwise, you get a memory leak.
Simply put, the "delete" command is only for objects allocated on the heap, because that's the manual memory management interface in C++ - new/delete. It is a command for the heap allocator, and the heap allocator doesn't know anything about stack allocated objects. If you try to call delete on a stack allocated object, you might as well have called it on a random memory address - they're the same thing as far as the heap allocator is concerned. Very much like trying to access an object outside array bounds:
int a[10];
std::cout << a[37] << "\n"; // a[37] points at... ? no one knows!
It just isn't meant to do that :)
Edit:
P.S. Memory leaks are more important when you are allocating memory in a function other than main. When the program ends, leaked memory gets deallocated, so a memory leak in main might not be a big deal, depending on your scenario. However, destructors never get called on leaked objects. If the destructor does something important, like closing a database or a file, then you might have a more serious bug on your hands.
stack memory is not being managed on the same way as heap memory.
there is no point to delete objects from stack: they will be deleted
automatically upon end of scope/function.