1

I would like to measure stack, heap and static memory separately because I have some constraints for each one.

To measure the heap memory I'm using valgrind->massif tool. Massif should also be possible to measure heap AND stack memory but it shows strange resultats :

  • Last snapshot without --stacks=yes provides total(B)=0, useful-heap(B)=0, extra-heap(B)=0 (so all is fine)

  • Last snapshot with --stacks=yes provides total(B)= 2,256, useful-heap(B)=1,040, extra-heap(B)=0, stacks(B)=1,208 (which shows memory leak even if it is the same command and same binary tested... dunno why ...)

So finally I need a tool to measure stack and static memory used by a c++ binary, some help would be welcome :)

Thanks for your help !

----------- EDIT --------------

Further to the Basile Starynkevitch comment, to explain what I mean with static, stack and heap memory I took it from the Dmalloc library documentation :

  • Static data is the information whose storage space is compiled into the program.

    /* global variables are allocated as static data */
    int numbers[10];
    
    main()
    {
            …
    }
    
  • Stack data is data allocated at runtime to hold information used inside of functions. This data is managed by the system in the space called stack space.

    void foo()
    {
            /* if they are, the parameters of the function are stored in the stack */
            /* this local variable is stored on the stack */
            float total;
            …
    }
    
    main()
    {
        foo();
    }
    
  • Heap data is also allocated at runtime and provides a programmer with dynamic memory capabilities.

    main()
    {
        /* the address is stored on the stack */
        char * string;
        …
    
        /*
         * Allocate a string of 10 bytes on the heap.  Store the
         * address in string which is on the stack.
         */
        string = (char *)malloc(10);
        …
    
        /* de-allocate the heap memory now that we're done with it */
        (void)free(string);
        …
    }
    
Bastienm
  • 363
  • 2
  • 16
  • Read [proc(5)](http://man7.org/linux/man-pages/man5/proc.5.html). For process 1234, consider running `cat /proc/1234/maps` in a terminal. – Basile Starynkevitch Feb 22 '18 at 09:16
  • I gave it a try to this. But I got some problem : (1) my binary is to do path planning. So it takes something like 50-400ms to run. Cause of this I can't really use the PID to check what is used in real time. (2) It does not provide the amount of memory stack/heap used, only an adress. I don't know what to do about this adress – Bastienm Feb 22 '18 at 16:01
  • 1
    From inside your program, you might read `/proc/self/maps` like [here](https://stackoverflow.com/a/12237783/841108) – Basile Starynkevitch Feb 22 '18 at 17:17
  • And I am not sure that "heap" memory or "static" memory is as easy to define as you want it to be... – Basile Starynkevitch Feb 22 '18 at 17:22
  • I edited my question to explain what I mean by heap, static and stacks – Bastienm Feb 23 '18 at 10:09
  • Many local variables are optimized to sit in registers. – Basile Starynkevitch Feb 23 '18 at 12:05
  • Even with the edit, the actual measure of "heap" memory or of "stack" memory is not what you expect.... – Basile Starynkevitch Feb 23 '18 at 12:06
  • On Linux specifically, consider also [mallinfo(3)](http://man7.org/linux/man-pages/man3/mallinfo.3.html). BTW, why is the result from `/proc/self/maps` read inside your program unsatisfactory? – Basile Starynkevitch Feb 23 '18 at 12:07
  • What are are your constraints on stack, heap and static memory and why are they separate? It seems weird to have *separate* memory constraints (at least on an ordinary Linux system). – Basile Starynkevitch Feb 23 '18 at 12:48

2 Answers2

3

I would like to measure stack, heap and static memory separately because I have some constraints for each one.

I cannot imagine why you have separate constraints for each one. They all sit in virtual memory! BTW you might use setrlimit(2) to set limits (perhaps from the invoking shell process, e.g. with bash ulimit builtin).

Your definitions are naive, if you consider the actual virtual address space of your process.

BTW, proc(5) enables you to query that space, e.g. using /proc/self/maps like here from inside your program (or /proc/1234/maps to query the process of pid 1234, perhaps from a terminal). You could also use /proc/self/status and /proc/self/statm (BTW try cat /proc/self/maps and cat /proc/$$/maps in a terminal). On Linux, you might also use mallinfo(3) and malloc_stats(3) to get information about memory allocation statistics.

Static data may be in the data segment (or BSS segment) of your program. But what about thread local space? And these data segments also contain data internal to various libraries, notably the C standard library libc.so (do that count?). Of course the stack segment is often bigger (since page aligned) than the actual used stack (from "bottom" to current %esp register). And a multi-threaded process has several stacks (and stack segments), one per thread.

Stack data is of course in the call stack, which contains a lot of other things (return addresses, gap, spilled registers) than just automatic variables (some of them sitting only in registers or being optimized by the compiler, without consuming any stack slot). Do they count? Also, startup code from crt0 (which calls your main) is likely to use a little bit of stack space (does it count?)...

Heap allocated data (it could be allocated from various libraries, or even from the dynamic linker) contains not only what your program gets from malloc (and friends) but also the necessary overhead. Do that count? And what about memory-mapped files? How should they count?

I would recommend querying the actual virtual address space (e.g. by reading /proc/self/maps or using pmap(1)...) but they you get something different than what you ask.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • My bad sorry. I do not not really have constraints on each but my boss want me to measure each one to know what is consume for what and if we can embed our code. For the "static memory" I directly use the bash function `size` on the binary. I know that the static variable not initialised are not counted in what is shown. To profile the heap memory I use valgrind. Thanks to this I get the biggest peak of allocation and the the total amout of memory allocated and freed. But as I am a beginner you "openned my eyes" and thakns for your help ! – Bastienm Feb 23 '18 at 14:50
2

Just BTW I found it before your answer :

  • To measure the heap memory use valgrind -> massif

  • To measure the static memory use the bash function size on the binary

  • To measure the stack it is possible to use stackusage

It gave me all the stats I wanted

Bastienm
  • 363
  • 2
  • 16
  • But these might be not want you want, because your notion of heap memory, static memory, stack is quite naive. – Basile Starynkevitch Feb 23 '18 at 16:00
  • I also think you should measure with `/proc/*/maps` – Basile Starynkevitch Feb 23 '18 at 16:10
  • btw, to measure the stack with /proc/self/maps I computed the difference between the two adress provided by the following line "**7ffc5d8c0000**-**7ffc5d8e3000** rw-p 00000000 00:00 0 [stack]". But I got something that I feel a bit too big. Is it the right way to do ? – Bastienm Mar 15 '18 at 14:33