Что это за незарезервированная, зарезервированная память в моем процессе? - PullRequest
6 голосов
/ 21 декабря 2010

Я использую VMMap из SysInternals для просмотра памяти, выделенной моим процессом Win32 C ++ на WinXP, и вижу кучу выделений, где части выделенной памяти зарезервированы, но не зафиксированы. Насколько я могу судить, из моего чтения и тестирования все общие распределители памяти (например, malloc, new, LocalAlloc, GlobalAlloc), используемые в программе на C ++, всегда выделяют полностью зафиксированные блоки памяти. Кучи - типичный пример кода, который резервирует память, но не фиксирует ее, пока не понадобится. Я подозреваю, что некоторые из этих блоков являются кучами Windows / CRT, но, похоже, таких блоков больше, чем я ожидал бы для куч. Я вижу порядка 30 из этих блоков в моем процессе, размером от 64 КБ до 8 МБ, и я знаю, что мой код никогда не намеренно вызывает VirtualAlloc для выделения зарезервированной, незафиксированной памяти.

Вот несколько примеров из VMMap: http://www.flickr.com/photos/95123032@N00/5280550393/

Что еще могло бы выделить такие блоки памяти, где большая часть ее зарезервирована, но не выделена? Будет ли иметь смысл, что мой процесс имеет 30 куч? Спасибо.

Ответы [ 3 ]

8 голосов
/ 05 января 2011

Я понял это - это куча CRT, которая выделяется при вызовах на malloc.Если вы выделяете большой кусок памяти (например, 2 МБ), используя malloc, он выделяет один зафиксированный блок памяти.Но если вы выделите более мелкие блоки (скажем, 177 КБ), то он зарезервирует 1 МБ памяти, но выделит только приблизительно то, что вы просили (например, 184 КБ для моего запроса 177 КБ).

Когда вы освобождаете этот маленький блок, этот больший блок размером 1 МБ не возвращается в ОС.Все, кроме 4k, не передано, но полный 1 МБ по-прежнему зарезервирован.Если вы снова позвоните malloc, он попытается использовать этот блок размером 1 МБ для удовлетворения вашего запроса.Если он не может удовлетворить ваш запрос памятью, которая уже зарезервирована, он выделит новый фрагмент памяти, который вдвое больше предыдущего (в моем случае это было от 1 МБ до 2 МБ).Я не уверен, продолжается ли эта схема удвоения или нет.

Чтобы вернуть вашу освобожденную память в ОС, вы можете позвонить _heapmin.Я бы подумал, что это сделает будущее большое выделение с большей вероятностью успешным, но все это будет зависеть от фрагментации памяти, и, возможно, heapmin уже будет вызван в случае сбоя выделения (?), Я не уверен.Это также приведет к снижению производительности, так как heapmin освободит память (что займет время), и тогда malloc потребуется перераспределить ее из ОС при необходимости снова.Эта информация относится к Windows / 32 XP, ваш пробег может отличаться.

ОБНОВЛЕНИЕ: В моем тестировании heapmin абсолютно ничего не делал.А куча malloc используется только для блоков размером менее 512 КБ.Даже если в куче malloc есть МБ непрерывного свободного пространства, он не будет использовать его для запросов более 512 КБ.В моем случае эта освобожденная, неиспользованная, но зарезервированная память malloc поглотила огромные части 2 ГБ адресного пространства моего процесса, что в итоге привело к сбоям выделения памяти.И поскольку heapmin не возвращает память в ОС, я не нашел решения этой проблемы, кроме перезапуска процесса или написания собственного менеджера памяти.

0 голосов
/ 15 мая 2013

Всякий раз, когда в вашем приложении создается поток, определенный (настраиваемый) объем памяти будет зарезервирован в адресном пространстве для стека вызовов потока. Нет необходимости фиксировать всю зарезервированную память, если вашему потоку фактически не понадобится вся эта память. Таким образом, только часть должна быть передана.

Если требуется больше выделенного объема памяти, можно будет получить больше системной памяти.

Практическое соображение заключается в том, что зарезервированная память является жестким ограничением размера стека, которое уменьшает доступное для приложения адресное пространство. Однако, используя только часть резерва, нам не нужно потреблять одинаковый объем памяти из системы до тех пор, пока он не понадобится.

Следовательно, каждый поток может иметь часть зарезервированной незафиксированной памяти. Я не уверен, каким будет тип страницы в этих случаях.

0 голосов
/ 22 декабря 2010

Могут ли они быть DLL-библиотеками, загруженными в ваш процесс? DLL (и исполняемый файл) - это память, отображаемая в адресное пространство процесса. Я считаю, что это изначально просто резервирует место. Пространство поддерживается самими файлами (по крайней мере на начальном этапе), а не файлом подкачки.

Только код, который на самом деле был затронут, вставлен в пейджер. Если я правильно понимаю терминологию, тогда он и будет зафиксирован.

Вы можете подтвердить это, запустив приложение в отладчике и посмотрев загруженные модули и сравнив их расположение и размеры с тем, что вы видите в VMMap.

...