I have a memory management problem in a C++ program. I reproduced my problem on a very small example. This example has no memory-leak (valgrind memcheck is ok).
I use a vector of pointers in a limited scope. In this scope, I append the vector and I can see memory rising (I print vsize and rss from /proc/self/stat).
I meet a problem when the limited scope ends. I think that memory would come back to its initial value because the vector has been cleaned and destroyed. In practise, vector's destruction has no effect on memory!
Furthermore, I could observe a weird side effect. If I do a stream action (eg. read a file) before the end of the limited scope, memory is freed!
Main Code:
#include <iostream>
#include <vector>
#include <unistd.h>
#include <ios>
#include <fstream>
#include <string>
using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::ios_base;
using std::ifstream;
void process_mem_usage(double &virtualSize, double &residentSetSize);
void printVectInfo(vector<int*> &o);
void monitoring();
void clearVector(vector<int*> &v);
void readFile();
void clearVector(vector<int*> &v) {
for (size_t i = 0; i < v.size(); ++i) delete v[i];
v.clear();
vector<int*> w;
v.swap(w);
}
int main() {
size_t N = 1<<20;
cout << "Size = " << N << endl;
monitoring();
// Limited scope
{
// Tmp vector limited to the current local scope
vector<int*> v;
v.reserve(N);
for (size_t i = 0; i < N; ++i) v.push_back(new int(i));
printVectInfo(v);
monitoring();
clearVector(v);
printVectInfo(v);
// readFile(); // this instruction solve the memory problem (paranormal instruction?!?)
}
// Here, vector has been destroyed
monitoring();
return 0;
}
Other functions (not important to understand the problem):
void process_mem_usage(double &virtualSize, double &residentSetSize) {
virtualSize = 0.0;
residentSetSize = 0.0;
// 'file' stat seems to give the most reliable results
ifstream stat_stream("/proc/self/stat", ios_base::in);
// dummy vars for leading entries in stat that we don't care about
string pid, comm, state, ppid, pgrp, session, tty_nr,
tpgid, flags, minflt, cminflt, majflt, cmajflt,
utime, stime, cutime, cstime, priority, nice,
num_threads, itrealvalue, starttime;
// the two fields we want
unsigned long vsize;
long rss;
stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
>> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
>> utime >> stime >> cutime >> cstime >> priority >> nice
>> num_threads >> itrealvalue >> starttime >> vsize >> rss;
stat_stream.close();
long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
virtualSize = vsize / 1024.0;
residentSetSize = rss * page_size_kb;
}
void printVectInfo(vector<int*> &o) {
cout << "------" << endl
<< "Vector: "
<< "size = " << o.size() << " / "
<< "capacity = " << o.capacity() << endl;
}
void monitoring() {
double vsize, rss;
usleep(1000000);
process_mem_usage(vsize, rss);
cout << "------" << endl
<< "Memory: "
<< "vsize = " << vsize << " / "
<< "rss = " << rss << endl;
}
void readFile() {
ifstream myfile("src/tmpFile.txt", std::ios::binary);
if (myfile.is_open()) myfile.close();
}
Result without readFile() instruction (showing the problem):
Size = 1048576
------
Memory: vsize = 12580 / rss = 1060
------
Vector: size = 1048576 / capacity = 1048576
------
Memory: vsize = 53512 / rss = 42244
------
Vector: size = 0 / capacity = 0
------
Memory: vsize = 45316 / rss = 34132
We can see an abnormal busy memory on the last monitoring.
Result with readFile() instruction (solve the problem):
Size = 1048576
------
Memory: vsize = 12580 / rss = 1060
------
Vector: size = 1048576 / capacity = 1048576
------
Memory: vsize = 53512 / rss = 42244
------
Vector: size = 0 / capacity = 0
------
Memory: vsize = 12580 / rss = 1488
We can see a small difference between begin and end busy memory, but memory snapshots are in the same order of magnitude. Result seems to be ok here.
Why there is differences of runtime?. Any help would be appreciated.
Details on my runtime context:
* gcc 4.6.3
* ubuntu 12.04 (x86-64)