Освободит ли free () память процесса?

8

Я запускаю программу C на ядре Linux 2.6.16. Я не думаю, что в моей программе есть утечки памяти, однако потребление памяти для программы остается стабильным после определенных операций и не уменьшается. Я использую команду «ps v» для отслеживания значения RSS моей программы.

Инструмент массива valgrind показывает, что большая часть кучи выделяется mmap в моем процессе. Но согласно коду эти распределения должны были быть освобождены после выполнения операций. Это потому, что освобожденная память все еще отображается и / или все еще вносит свой вклад в значение RSS процесса?

Любое понимание будет очень оценено!

Ниже приведен фрагмент отчета о массиве Вальгринд. Примечание. Я включил параметр --pages-as-heap для инструмента массива, чтобы измерить всю память, используемую программой.

--------------------------------------------------------------------------------
  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: ???
| |   |
......
Michelle
источник
Почему ты не используешь munmap? munmap (2)
Микел
Вы используете общие библиотеки? Можете ли вы предоставить соответствующие части продукции, valgrindа также /proc/<PID>/maps?
Микель
Мы не используем munmap, так как glibc malloc и free имеют свои реализации. Да, используются общие библиотеки. Почему это имеет значение? Соответствующие части отчета valgrind добавлены к основному вопросу.
Мишель
См. UNIX против освобождения памяти Windows
Жиль "ТАК, перестань быть злым"
@michelle Я думал, ты имел в виду, что звонишь mmap. Но теперь я думаю, что понимаю: ты звонишь malloc/ calloc, и это звонит mmap?
Микель

Ответы:

5

Функция библиотеки C free()может, но не обязана, возвращать память ядру.

Некоторые реализации malloc()переносят границу между «кучей» и иным образом неиспользуемым адресным пространством («разрыв системы») через sbrk()системный вызов, а затем распределяют меньшие части этих больших выделений. Без перераспределения каждого меньшего фрагмента free()невозможно вернуть память в ОС.

Та же самая причина применима к malloc()реализациям, которые не используют sbrk(2), но, возможно, используют mmap("/dev/zero")или что-то еще ... Я не могу найти ссылку, но мне кажется, что я помню, что тот или иной из BSD использовал mmap()этот способ для получения страниц памяти. Тем free()не менее, нельзя вернуть страницу в операционную систему, пока программа не освободит все перераспределения.

Некоторые malloc()реализации возвращают память системе: ChorusOS (?), Очевидно, сделал. Не ясно, сдвинул ли он системный разрыв или munmap()'edстраницы.

Вот статья о распределителе памяти, которая повышает производительность, «настойчиво отдавая свободные страницы менеджеру виртуальной памяти». Слайд-шоу для разговора о распределителе.

Брюс Эдигер
источник
Я понимаю, что free () не возвращает память в ОС. Но выполняет ли free () отображение памяти или память остается отображаемой с помощью распределителя памяти glibc?
Мишель
msgstr "free () не может вернуть страницу в операционную систему, если программа не освобождает каждое перераспределение." Я не очень понимаю это. Не могли бы вы объяснить «перераспределение»?
Мишель
1
@michelle: допустим, размер страницы составляет 4192 байта. Программа вызывает malloc (4186), а затем malloc (8). Программа выделила всю страницу. Программа вызывает free () с выделением 4186 байт. Функция free () не может отменить отображение страницы, поскольку 8-байтовое распределение не было свободным ().
Брюс Эдигер
В этом есть смысл. Спасибо, Брюс. Поэтому я предполагаю, что когда страница все еще отображается, все данные на ней все еще учитываются при измерении valgrind, хотя некоторые уже освобождены. Правильный?
Мишель