4

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 Answers2

5

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.

that other guy
  • 116,971
  • 11
  • 170
  • 194
0

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.

Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • If i try to allocate enough memory with the new call, wouldn't it be forced to allocate a new chunk and hence increase maxrss? Valgrind isn't an option for me as this will ultimately be on an embedded system which won't be able to run it. – John.smith16 Jul 11 '18 at 17:57
  • @John.smith16 `new` would return a pointer into an old or new chunk, you don't know. Use Valgrind in your desktop develpment environment, do the test there. When all leaks are solved, move to the embedded system. – Ripi2 Jul 11 '18 at 18:00
  • 1
    I mean if the memory im trying to allocate is large enough that there couldn't be an old chunk big enough. For example im getting a maxrss of 15000kb, if i try to allocate more than 15000kb wouldn't that force a new chunk to be allocated? – John.smith16 Jul 11 '18 at 18:05