Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am running a C program on Linux 2.6.16 kernel. I do not think there are memory leaks in my program however the memory consumption for the program remains stable after certain operations and does not decrease. I use the 'ps v ' command to monitor the RSS value of my program.

The valgrind massif tool shows a large portion of heap is allocated by mmap in my process. But according to the code those allocations should have been freed after the operations are done. Is it because the freed memory is still mapped and/or still contributes to the RSS value of the process?

Any insight will be very appreciated!

Below is the snip from the valgrind massif report. Note I have turned on the --pages-as-heap option for the massif tool to measure all memories used by the program.

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 85 701,483,989,262      173,576,192      173,576,192             0            0
 86 704,352,949,469      173,367,296      173,367,296             0            0
 87 707,582,275,643      173,367,296      173,367,296             0            0
 88 710,536,145,814      173,367,296      173,367,296             0            0
100.00% (173,367,296B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->53.40% (92,581,888B) 0x649248B: mmap (in /lib64/tls/libc.so.6)
| ->41.13% (71,303,168B) 0x6446D85: _int_malloc (in /lib64/tls/libc.so.6)
| | ->39.31% (68,157,440B) 0x6448D62: calloc (in /lib64/tls/libc.so.6)
......[my own functions are omitted]
->35.28% (61,157,376B) 0x400F51B: mmap (in /lib64/ld-2.3.3.so)
| ->28.81% (49,954,816B) 0x4004CE8: _dl_map_object_from_fd (in /lib64/ld-2.3.3.so)
| | ->28.81% (49,954,816B) 0x400636B: _dl_map_object (in /lib64/ld-2.3.3.so)
| |   ->18.89% (32,755,712B) 0x400AB42: openaux (in /lib64/ld-2.3.3.so)
| |   | ->18.89% (32,755,712B) 0x400AF7C: _dl_catch_error (in /lib64/ld-2.3.3.so)
| |   |   ->18.89% (32,755,712B) 0x4009FCF: _dl_map_object_deps (in /lib64/ld-2.3.3.so)
| |   |     ->18.89% (32,755,712B) 0x40021FD: dl_main (in /lib64/ld-2.3.3.so)
| |   |       ->18.89% (32,755,712B) 0x400E7F6: _dl_sysdep_start (in /lib64/ld-2.3.3.so)
| |   |         ->18.89% (32,755,712B) 0x4001477: _dl_start (in /lib64/ld-2.3.3.so)
| |   |           ->18.89% (32,755,712B) 0x4000CF6: ??? (in /lib64/ld-2.3.3.so)
| |   |             ->18.89% (32,755,712B) 0x0: ???
| |   |               ->18.89% (32,755,712B) 0x7FF0003D5: ???
| |   |                 ->18.89% (32,755,712B) 0x7FF0003E4: ???
| |   |
......
share|improve this question
    
Why aren't you using munmap? munmap(2) –  Mikel Oct 31 '12 at 20:49
    
Are you using shared libraries? Can you provide relevant parts of output from valgrind as well as /proc/<PID>/maps? –  Mikel Oct 31 '12 at 21:08
    
We do not use munmap since glibc malloc and free has the implementations. Yes shared libraries are used. Why does that matter? The relevant parts of valgrind report is added to the main question. –  michelle Oct 31 '12 at 23:06
    
See UNIX vs Windows memory deallocation –  Gilles Oct 31 '12 at 23:53
    
@michelle I thought you meant you were calling mmap. But now I think I understand: You're calling malloc/calloc, and it's calling mmap? –  Mikel Nov 1 '12 at 2:00
show 2 more comments

1 Answer 1

The C-library function free() can, but does not have to, return memory to the kernel.

Some implementations of malloc() move the boundary between "heap" and otherwise unused address space (the "system break") via the sbrk() system call, then dole out smaller pieces of those large allocations. Without getting every smaller piece de-allocated, free() can't really return the memory to the OS.

That same reason applies to malloc() implementations that don't use sbrk(2), but maybe use mmap("/dev/zero") or something.. I can't find a reference, but I seem to remember that one or another of the BSD's used mmap() that way to get pages of memory. Nevertheless, free() can't return a page to the operating system unless every sub-allocation is deallocated by the program.

Some malloc() implementations do return memory to the system: ChorusOS(?) apparently did. It's not clear if it moved the system break, or munmap()'ed pages.

Here's a paper about a memory allocator that improves performance by "aggressively giving up free pages to the virtual memory manager". Slide show for a talk about the allocator.

share|improve this answer
    
I understand free() does not return memories to OS. But does free() unmap the memory or does the memory remain to be mapped by the glibc memory allocator? –  michelle Oct 31 '12 at 19:43
    
"free() can't return a page to the operating system unless every sub-allocation is deallocated by the program." I do not really understand this. Could you explain 'sub-allocation'? –  michelle Oct 31 '12 at 19:45
    
@michelle: suppose a page size of 4192 bytes. A program calls malloc(4186) and then malloc(8). The program has allocated all of a page. The program calls free() on the 4186-byte allocation. free() cannot unmap the page because the 8-byte-allocation has not been free()'ed. –  Bruce Ediger Oct 31 '12 at 20:58
    
That makes sense. Thanks Bruce. So my guess is when the page is still mapped, all data in it are still taken into consideration by valgrind measurement though some are already freed. Correct? –  michelle Nov 1 '12 at 12:24
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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