3

I am trying to learn more about how memory is handled in C++, and I have a question about how memory is released when a variable is reassigned. To monitor memory consumption, I have a (Linux-specific) function CheckMem() which calls pmap to see how much memory the process is using. I then simply create a vector of size 1, reassign it to a vector of size one million, then reassign it again to size 1, and observe how the memory changes.

#include <iostream>
#include <vector>
#include <sstream>
#include <cstdio>
#include <unistd.h>

using namespace std;

void CheckMem()
{
  char cmdstring[100],outbuf[500],buf[100];
  sprintf(cmdstring,"pmap -x %d | tail -1",getpid()); 
  FILE* output = popen(cmdstring,"r");
  fgets(outbuf,500,output);
  size_t kb,rss,dirty;
  istringstream ss(outbuf);
  ss >> cmdstring >> buf >> kb >> rss >> dirty;
  cout << "RSS: " << rss << " KB" << endl;
}

int main()
{
 vector<double> vd(1);
 CheckMem();
 vd = vector<double>(1000000);
 CheckMem();
 vd = vector<double>(1);
 CheckMem();
 return 0;
}

If I compile with g++ (gcc version 4.8.4), I get the following output:

RSS: 1184 KB
RSS: 9128 KB
RSS: 9136 KB

It appears that the memory used for the large vector (1 million doubles ~ 8 MB) is not released when the vector is reassigned to size 1. However, if I compile with the flag -std=c++11, then the output changes:

RSS: 1180 KB
RSS: 9112 KB
RSS: 1300 KB

Now the memory appears to be released by the reassignment. Does the C++11 standard somehow treat memory differently for reassignments?

ragnar
  • 143
  • 4

2 Answers2

3

More than likely the implementers of the library are reusing the capacity of the vector as long as it is greater than the capacity of the vector you are assigning to it. This way they save a memory allocation.

Starting in C++11 we have move assignment so when you compile with -std=c++11 instead of reusing the capacity the temporary vector is moved into the existing vector and the content of the original vector are moved into the temporary. At then end of the expression the temporary is destroyed and you now have a vector with a smaller capacity.

If you want to shrink the capacity of the vector you should check out: reduce the capacity of an stl vector

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Yep. That seems to be what's going on. If I add a `vector(0).swap(vd)`, then the memory is released in both cases. – ragnar Oct 16 '15 at 18:35
  • A citation pointing out where it states or implies that the assigned-to vector reuses the assigned-from vectors storage would be useful. Last time I looked, I thought that was underspecified, but I might be remembering wrong. – Yakk - Adam Nevraumont Oct 16 '15 at 20:03
  • @Yakk I said *More than likely* to cover that this may not be the issue but it could be. Should I clarify that more? – NathanOliver Oct 16 '15 at 20:05
0

The difference is the move assign which was introduced in C++11. Before that you only had copy constructor which would copy you new vector into the old vector if capacity is big enough.

With C++11 and the move assign the new vector's data replaces the old ones which is then destroyed.

Surt
  • 15,501
  • 3
  • 23
  • 39