How to correctly deallocate or delete a c++ vector? - c++

I have a weird problem with vector in C++..
I created a vector and inserted 10000 integer values into it and have checked the memory utilization. It is 600 kb. But after i erased the vector, still my system monitor says the program uses 600 kb.
Can anyone explain why the memory is not getting freed even after i erase the vector
Note: I have used all the methods for deletion(erase,pop_front,pop_back,clear...Even then I have the same problem)
Thanks and regards...:)

Presumably you checked memory with some system utility. Even if the vector space is freed on the heap that does not mean the heap space itself is going to be returned to the OS and reflected in the values shown in the system utility.

The only way to really get rid off unused memory in a std::vector<> pre C++11 is to swap it with an empty vector: vector<int>().swap(myvec). In C++11 you have a member function shrink_to_fit which often is implemented as the swap idiom just mentioned.

The C++ vector reserves more memory than it needs for its elements to speed up adding new elements and it doesn't free the reserved memory, after the elements have been deleted.
You can try swapping the vector with itself, to make the amount of reserved memory match the actual size of all the elements: v.swap(v)

Try deleting each element and then deleting the vector itself - see if that makes any difference.
Have you tried using valgrind to find out if there are any memory leaks?

Try using the erase-remove idiom. If you are just erasing all of the elements from the vector then all you are doing is moving the end() iterator. So everything is still there in the vector but "unavailable".
http://en.wikipedia.org/wiki/Erase-remove_idiom

The following code gives the answer:
#include <cstdio>
#include <vector>
struct Foo
{
~Foo()
{
printf("~Foo()\n");
}
};
int main()
{
std::vector<Foo> v;
v.push_back(Foo());
// This causes all Foo instances to be released as well as all
// space allocated by the vector to be released.
v = std::vector<Foo>();
// As you can see, all printf("~Foo()\n") calls happen before this
// line is printed.
printf("~~~~~~~~~~~~~~\n");
return 0;
}

Related

How to free memory for vector of vectors (C++)

I have a vector<vector<double>> elem and I want to deallocate its memory many times in my program.
I tried using
vector<vector<double>>().swap(elem);
Or even a for cicle
for(int i=0; i<elem.size();i++)
vector<double>().swap(elem[i]);
vector<vector<double>>().swap(elem);
elem.resize(dim, vector<double>(0));
(I want the first dimension to be a certain number dim)
But when I call
cout<<elem[0].size();
numerous times in my program, the output keeps growing, even if I've just used the aforementioned method. This issue isn't present with the "main" size of the vector.
i.e.
cout<<elem.size();
always outputs dim
EDIT: I know about clear() but I want to deallocate the vector, shrink_to_fit() doesn't work either. Also this is implemented in a function out of the main one, as follows:
void arrayReset(vector<vector<double>> elem) {
for(int i=0; i<elem.size();i++)
vector<double>().swap(elem[i]);
vector<vector<double>>().swap(elem);
elem.resize(dim, vector<double>(0));
}
Your new function void arrayReset(vector<vector<double>> elem) { gets a COPY of your vector and [possibly] cleans it; you never see it in the calling function.
If you pass your vector by reference, you would manipulate the original vector.
How to free memory for vector
The way is the same for all vectors regardless of the element type.
Step 1: Remove the elements of the vector. Simplest way is the clear member function. After this step, the size member function will return 0.
Step 2: Call shrink_to_fit member function which requests the memory to be deallocated. After this step, capacity may return 0.
Technically, shrink_to_fit is a request that is not required to be honoured by the language implementation. The only guaranteed way to deallocate the memory is to destroy the vector. Example:
{
std::vector<std::vector<double> vector;
// use vector here
}
// memory has been deallocated
I want to deallocate its memory many times in my program.
Note that this is typically slower than not deallocating many times. I recommend making sure that you want something that is actually useful.

Any way that we can prevent the breakdown between reference and object when resize a vector?

I was debugging an issue and realized that when a vector is resizing, the reference will not work anymore. To illustrate this point, below is the minimal code. The output is 0 instead of 1. Is there anyway that we can prevent this happen except reserving a large space for x?
#include <iostream>
#include <vector>
using namespace std;
vector<int> x{};
int main(){
x.reserve(1);
x.push_back(0);
int & y = x[0];
x.resize(10);
y=1;
cout << x[0] << endl;
return 0;
}
This is called invalidation and the only way you can prevent it is if you make sure that the vector capacity does not change.
x.reserve(10);
x.push_back(0);
int &y = x[0];
x.resize(10);
The only way I can think of is to use std::deque instead of std::vector.
The reason for suggesting std::deque is this (from cppreference):
The storage of a deque is automatically expanded and contracted as
needed. Expansion of a deque is cheaper than the expansion of a
std::vector because it does not involve copying of the existing
elements to a new memory location.
That line about not copying is really the answer to your question. It means that the objects remain where you placed them (in memory) as long as the deque is alive.
However, on the very next line it says:
On the other hand, deques typically have large minimal memory cost; a
deque holding just one element has to allocate its full internal array
(e.g. 8 times the object size on 64-bit libstdc++; 16 times the object
size or 4096 bytes, whichever is larger, on 64-bit libc++).
It's now up to you to decide which is better - higher initial memory cost or changing your program's logic not to require referencing the items in the vector like that. You might also want to consider std::set or std::unordered_set for quickly finding an object within the container
There are several choices:
Don't use a vector.
Don't keep a reference.
Create a "smart reference" class that tracks the vector and the index and so it will obtain the appropriate object even if the vector moves.
You can create a vector of std::shared_ptr<> as well and keep the values instead of the interators.

Safe to iterate over std::vector<some_container> while modifying <some_container>'s size?

Suppose I have a vector of some other container type. While iterating over the vector I change the size of the containers. Given that vectors try to remain contiguous in system memory, could the pointer arithmetic fail in loops like this? For example,
#include <stdlib.h>
#include <vector>
using namespace std;
int main(){
vector<vector<double> > vec_vec(4);
for (auto i=vec_vec.begin(); i!=vec_vec.end(); ++i){
for (double j=0; j<100; j+=1.0){
i->push_back(j)
};
};
return 0;
}
I've had no issues using code like this so far, but now I'm wondering if I just got lucky. Is this safe? Does it depend on the kind of container used inside the vector?
That's perfectly OK, you are not changing the outer vector. However there is no guarantee that all vectors will be contiguous in the memory. Each individual inner one will be, but don't expect that they are arranged one after the other in memory.
You are modifying the contents of the std::vector you are iterating over. No the vector you are iterating over. They are different things.
First one is safe. Second one wouldn't be safe due to eventual memory reallocations.
A vector is a fixed size management object (size,reserved, pointer) with its contiguous memory pointed to by pointer.
Thus you are not changing object's size

Implementation defined to use a reserved vector without resizing it?

Is it implementation defined to use a reserved vector without resizing it?
By that I mean:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<unsigned int> foo;
foo.reserve(1024);
foo[0] = 10;
std::cout<<foo[0];
return 0;
}
In the above, I reserve a good amount of space and I assigned a value to one of the indices in that space. However, I did not call push_back which "resizes" the vector and gives it a default value for each element (which I'm trying to avoid). So in this foo.size() is 0 while foo.capacity() is 1024.
So is this valid code or is it implementation defined? Seeing as I'm assigning to a vector with "0" size. It works but I'm not sure if it's a good idea..
The reason I'm trying to avoid the default value is because for large allocations, I don't need it "zero-ing" out each index as I will decide when I want to write to it or not. I'd use a raw pointer but the lodepng API accepts only a vector for decoding from file.
std::vector::reserve just reserves memory, so the next push_back does not have to allocate memory. It does not change the size of the vector.
If you want a vector with an initial size of 1024 elements, you can use the constructor to do that:
std::vector<unsigned int> foo(1024);
Note that if you create a vector with an initial size of e.g. 1024 elements, if you then do push_back you add an element, so the size of the vector increases to 1025 elements.
It is illegal, regardless of the type of item in the container or what seems to happen on a particular compiler. From 23.1.1/12 (Table 68) we learn that operator[] behaves like *(a.begin() + n). Since you haven't added any items to the container this is the same as accessing an iterator past end() which is undefined.

std::vector pointer with data swap

In the section of code below, what would be the resultant memory structure after the swap? Would there be a leak because they have swapped memory addresses underneath? Would it be fine because they did a deep copy? what if this code was stuck inside of a class and I was swapping a working buffer with a piece of dynamic memory?
#include <iostream>
#include <vector>
int main()
{
std::vector<std::string> * ptr_str_vec =
new std::vector<std::string>();
ptr_str_vec->push_back("Hello");
std::vector<std::string> str_vec;
str_vec.push_back("World");
ptr_str_vec->swap(str_vec);
delete ptr_str_vec;
//What would be the resulting structures?
return 0;
}
EDIT: Posted slightly faulty code. Fixed the errors.
When a vector is created, the underlying continuous data block used by vector is by default created from heap. In your case, since you didn't supply allocator, default one is used.
int main()
{
std::vector<std::string> * ptr_str_vec =
new std::vector<std::string>(); // #^&! *ptr_str_vec is allocated from heap. vector's data block is allocated from heap.
ptr_str_vec->push_back("Hello"); // #^&! "hello" is copied onto heap block #1
std::vector<std::string> str_vec; // #^&! str_vec is allocated from stack. vector's data block is allocated from heap.
str_vec.push_back("World"); // #^&! "world" is copied onto heap block #2
ptr_str_vec->swap(str_vec); // #^&! swap is fast O(1), as it is done by swapping block #1 and #2's address. No data copy is done during swap.
delete ptr_str_vec; // #^&! delete ptr_str_vec as well as heap block #2.
//What would be the resulting structures? /
return 0; // #^&! delete str_vec as well as heap block #1
}
The values in each vector will be swapped http://www.cplusplus.com/reference/vector/vector/swap/
I see no memory leak (other than the one you get when your program ends at the end of main, since you aren't deleting your pointer), your ptr_str_vec pointer does not change, only the data inside the vector that it points to changes
Assuming that you are already familiar with swap, is there any reason that you haven't set it up so you can test the output to see what it does yourself? This will be the quickest way to assure yourself that you know exactly what it is doing and if your use of it is appropriate.
In this case, the resulting structures are simply that ptr_str_vec points to a vector containing a std::string("World") and str_vec is a vector containing a std::string("Hello"). Your example suffers from many faults in answering your question, in particular because you only have a single element in each vector (and thus the vectors are equal length), and because the elements are the exact same size (and thus the vectors occupy approximately equivalent memory segments). In a running instance of your full project, it is very likely that none of these conditions are true.