2

I am trying to figure out what eats lots of memory in a process, therefore I tried reading /proc/pid/smaps (where pid is the pid of the process).

What boggles me is that some entries do not have names. For example:

4805d000-4805e000 rwxp 0001d000 00:0b 19674210   /lib/ld-2.6.so
Size:                  4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
4805e000-4805f000 ---p 00000000 00:00 0 
Size:                  4 kB
Rss:                   0 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
4805f000-4885e000 rwxp 00000000 00:00 0 
Size:               8188 kB
Rss:                8188 kB
Pss:                8188 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:      8188 kB
Referenced:         8188 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB

Above, the first entry has name /lib/ld-2.6.so, but second and third do not have any name. So, what are those nameless entries? How to find out which library created them?


Out of curiosity, is there anything else (other then valgrind) to try to figure out what eats memory in a program?


After digging into kernel's code, I found out that these entries can indeed not be mapped to any file (fs/proc/task_mmu.c). But the question still stands: what are they? mmap() as a way to allocate memory?

2

Nameless areas can be created via a sufficiently large malloc:

#include <sys/types.h>    
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    int *ip;
    char *before, *after;

    asprintf(&before, "cat /proc/%d/smaps > before", getpid());
    asprintf(&after, "cat /proc/%d/smaps > after", getpid());

    system(before);

    ip = malloc(9999999);
    if (!ip) abort();

    system(after);
    return 0;
}

As shown by

$ CFLAGS=-g make ilikebigmallocs
cc -g    ilikebigmallocs.c   -o ilikebigmallocs
$ ./ilikebigmallocs 
$ diff before after
64a65,80
> 7f97425ac000-7f9742f36000 rw-p 00000000 00:00 0 
> Size:               9768 kB
> Rss:                   4 kB
...

so at least some of your areas were likely created by malloc or equivalent (which under the hood calls mmap). strace (or sysdig) can log these:

$ strace -e trace=memory -o blah ./ilikebigmallocs
$ awk '/^mmap/{print $NF}' blah
0x7fc6193b1000
0x7fc6193a6000
...
$ grep 7fc6193b1000 after
7fc6193b1000-7fc6193b2000 rw-p 00000000 00:00 0 
$ 

I guess you could use gdb or a malloc tracer or other means to resolve a specific mmap back up to specific code in your memory-hungry process...

  • Yes, you are right. Found somewhere that memory allocation greater then 128k uses mmap(). Now I can't find the link to that article :( – BЈовић May 5 '17 at 5:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.