I am debugging a slow memory leak in a large C++ application, I'd like to print out the current heap size at various points in the program.
Aside from opening and parsing /proc/PID/statm
is there any library API call from which I can get this information?
One post suggested sbrk()
, however, that returns the current heap pointer – not 100% what I want. (second question: do changes in the sbrk()
value correspond to changes in the current heap size?)
I've looked but it seems strange that there'd be no system call...
Thanks
UPDATE I
I've done some test comparision between calling sbrk()
and reading proc/.../statm
. It appears that sbrk()
does not reflect actual allocations. Instead it appears that statm
measures actual allocations while sbrk()
shows the total heap size.
This total heapsize increments in big chunks (equal to page size?).
The test program below produces this output (Heap Size as reported by sbrk()
and memory usage as reported by /proc/.../statm
, clearly showing a difference:
0 ALLOC: HEAP SIZE: 0
MEMORY USAGE: 1308 201 174 2 0 566 0
1 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 1565 212 184 2 0 823 0
2 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 1822 216 187 2 0 1080 0
3 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 2079 217 187 2 0 1337 0
4 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 2336 218 187 2 0 1594 0
5 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 2593 219 187 2 0 1851 0
0 FREE: HEAP SIZE: 135168
MEMORY USAGE: 3364 225 189 2 0 2622 0
1 FREE: HEAP SIZE: 135168
MEMORY USAGE: 3107 224 189 2 0 2365 0
2 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2850 223 189 2 0 2108 0
3 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2593 222 189 2 0 1851 0
4 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2336 221 189 2 0 1594 0
5 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2079 220 189 2 0 1337 0
Test Program
class CfgProfileList
{
public:
bool obtainSystemProfileList();
void leakObjTest();
std::set<std::string> mProfileList;
private:
char dummy[1024 * 1024]; // use up some space
};
class ComUtil
{
public:
static void printMemoryUsage();
private:
static unsigned int mHeapOrigin;
};
/* static */
unsigned int ComUtil::mHeapOrigin = 0;
// Print current process memory utilization
/* static */ void
ComUtil::printMemoryUsage()
{
unsigned int pHeap = (unsigned int)sbrk(0);
if (mHeapOrigin == 0)
mHeapOrigin = pHeap;
printf("HEAP SIZE: %u\n", pHeap - mHeapOrigin);
char fname[256], line[256];
sprintf(fname, "/proc/%d/statm", getpid());
FILE *pFile = fopen(fname, "r");
if (!pFile)
return;
fgets(line, 255, pFile);
fclose(pFile);
printf("MEMORY USAGE: %s", line);
}
void
CfgProfileList::leakObjTest()
{
CfgProfileList *pointerList[50];
int n = 10;
int sleep = 100000;
printf("OBJECT ALLOCATION\n");
for (int i = 0; i < n; i++)
{
pointerList[i] = new CfgProfileList;
printf("%d ALLOC: ", i);
ComUtil::printMemoryUsage();
usleep(sleep);
}
printf("\n");
for (int i = 0; i < n; i++)
{
delete pointerList[i];
printf("%d FREE: ", i);
ComUtil::printMemoryUsage();
usleep(sleep);
}
}
int
main(int argc, char **argv)
{
CfgProfileList pl;
pl.leakObjTest();
}