Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect programmatically count of bytes allocated by process on Heap?

Tags:

c++

linux

How to detect programmatically count of bytes allocated by process on Heap? This test should work from process itself.

like image 763
Pirks Avatar asked Nov 08 '09 14:11

Pirks


3 Answers

I think mallinfo() is what you want:

#include <malloc.h>


struct mallinfo *info;

info = mallinfo();

printf ("total allocated space:  %llu bytes\n", info->uordblks);
printf ("total free space:       %llu bytes\n", info->fordblks);

The struct mallinfo structure is technical, and specific to the malloc() implementation. But the information you want is in there. Here is how I report the values:

mallinfo.arena = "Total Size (bytes)" 
mallinfo.uordblks = "Busy size (bytes)" 
mallinfo.fordblks = "Free size (bytes)" 
mallinfo.ordblks = "Free blocks (count)" 
mallinfo.keepcost = "Top block size (bytes)" 
mallinfo.hblks = "Blocks mapped via mmap() (count)" 
mallinfo.hblkhd = "Bytes mapped via mmap() (bytes)"

These two are allegedly not used, but they seem to change on my system, and thus might be valid:

mallinfo.smblks = "Fast bin blocks (count)"
mallinfo.fsmblks = "Fast bin bytes (bytes)"

And the other interesting value is returned by "sbrk (0)"

like image 77
Martin Del Vecchio Avatar answered Sep 24 '22 02:09

Martin Del Vecchio


There are a number of possibilities.

How accurate do you need it to be? You can get some useful data via cat /proc/${PID}/status | grep VmData.

You can #define your own malloc(), realloc(), calloc(), and free() functions, wrapping the real functions behind your own counter. You can do really cool things here with __FILE__, __LINE__, & __func__ to facilitate identifying core leaks in simple tests. But it will only instrument your own code!

(Similarly, you can also redefine the default operator new and operator delete methods, both array and non-array variants, and both throwing std::bad_alloc and std::nothrow_t variants. Again, this will only instrument your own code!)

(Be aware: On most C++ systems, new ultimately invokes malloc(). It doesn't have to. Especially with in-place new! But typically new does make use of malloc(). (Or it operates on a region of memory that has previously been malloc()'ed.) Otherwise you'd get into really funky stuff with multiple heap managers...)

You can use sbrk(0) to see where the data segment is currently set. That's not so great. It's a very coarse measurement, and it doesn't account for holes (unused memory regions) in the heap. (You're much better off with the VmData line from /proc/${PID}/status.) But if you're just looking for a general idea...

You can trap malloc()/free()/etc by writing your own shared library and forcing your process to use it instead of the real versions via LD_PRELOAD. You can use dlopen()/dlsym() to load & invoke the *real* malloc()/free()/etc. This works quite beautifully. The original code is unmodified, not even recompiled. But be aware of re-entrant situations when coding this library, and that your process will initially invoke malloc()/calloc()/realloc() before dlopen()/dlsym() can complete loading the real functions.

You might check out tools like Valgrind, though that's really aimed more at memory leaks.


Then again, perhaps mtrace() is what you want? Or __malloc_hook? Very proprietary (GNU) & nonstandard... But you are tagged "Linux"...

like image 41
Mr.Ree Avatar answered Sep 23 '22 02:09

Mr.Ree


There's no easy, automatic way to do it, if that's what you're asking. You basically have to manually keep track of heap allocations yourself using a counter variable. The problem is that it's difficult to control which parts of your program are allocating memory on the heap, especially if you're using a lot of libraries out of your control. To complicate things further, there's two ways a program might allocate heap memory: new or malloc. (Not to mention direct OS calls like sbrk.)

You can override global operator new, and have each call to new increase a global tally. However, this won't necessarily include times when your program calls malloc, or when your program uses some class-specific new override. You can also override malloc using a macro, but this is not necessarily portable. And you'd also have to override all the variations of malloc, like realloc, calloc, etc. All of this is further complicated by the fact that on some implementations, new itself may call malloc.

So, essentially, it's very difficult to do this properly from within your program. I'd recommend using a memory profiler tool instead.

like image 31
Charles Salvia Avatar answered Sep 25 '22 02:09

Charles Salvia