Linux getrusage() maxrss maximum resident set size not increasing with allocation (C++)

1.4k views Asked by At

I am trying to use getrusage(.) and maximum resident set size (maxrss) to check for memory leaks. However, when i purposely try to create a leak, maxrss does not change. Maybe i am not understanding maxrss deeply enough. Here is the code:

#include <iostream>
#include <sys/time.h>
#include <sys/resource.h>
using namespace std;
int main() {
  struct rusage r_usage;
  getrusage(RUSAGE_SELF, &r_usage);
  cout << r_usage.ru_maxrss << "kb\n";
  cout << "Allocating...\n";
  int a = 100000; // have tried range of numbers
  int* memleaktest = new int[a]; // class member
  if(!memleaktest)
    cout << "Allocation failed";
  getrusage(RUSAGE_SELF, &r_usage);
  cout << "after allocation " << r_usage.ru_maxrss << "kb\n";
  return 0;
}

I get the exact same value after allocatoin (~15000kb). On Ubuntu x86.

2

There are 2 answers

0
that other guy On BEST ANSWER

Allocated memory isn't actually mapped until you access it. If you initialize the array with values, Linux is forced to actually allocate and map new pages:

#include <iostream>
#include <sys/time.h>
#include <sys/resource.h>
using namespace std;
int main() {
  struct rusage r_usage;
  getrusage(RUSAGE_SELF, &r_usage);
  cout << r_usage.ru_maxrss << "kb\n";
  cout << "Allocating...\n";
  int a = 1000000;                 // Sufficiently large
  int* memleaktest = new int[a](); // Initialized to zero
  if(!memleaktest)
    cout << "Allocation failed";
  getrusage(RUSAGE_SELF, &r_usage);
  cout << "after allocation " << r_usage.ru_maxrss << "kb\n";
  return 0;
}

On my system, this results in:

4900kb
Allocating...
after allocation 6844kb

Note that compiler optimizations may decide that the array is unused or should be allocated up front, so prefer compiling without them or rewriting the test case in such a way that it can't be optimized.

3
Ripi2 On

Due to performance issues the Operating System (OS) allocates resources in chuncks, not each app-request is a new resource. So, when a block of memory is released in the app, the OS may still reserve the chunck where it belongs to.

Why? Consider an app requesting 1G of different 1 byte memory blocks. The OS must track all of them, which means that the total amount of memory is 1G plus 2G*sizeof(pair) needed to store the pairs {begin, size} to identify each memory block.

If you want to detect memory leaks use the good old Valgrind tool.