Выделение не освобождает память в приложении Windows / C ++

Мое приложение для Windows / C ++ выделяет ~ 1 ГБ данных в памяти оператору newи обрабатывает эти данные. После обработки данные удаляются.

Я заметил, что если я снова запускаю обработку, не выходя из приложения, второй вызов оператору newдля выделения ~ 1 ГБ данных не выполняется.

Я ожидаю, что Windows вернет память. Можно ли лучше управлять этим с помощью некоторых других вызовов Win32 и т. Д.?

15.12.2008 11:49:31
5 ОТВЕТОВ

Я не думаю, что это проблема Windows. Проверьте, правильно ли вы использовали delete или delete []. Возможно, это поможет, если вы разместите код, который выделяет / освобождает память.

6
15.12.2008 11:53:30

Это может произойти из-за фрагментации памяти (в действительности, фрагментации адресного пространства), когда различные факторы внесли свой вклад в адресное пространство вашей программы, не имея доступной непрерывной дыры в 1 ГБ. На самом деле, я подозреваю ошибку в вашем управлении памятью (извините) - вы запускали свой код с помощью обнаружения утечек?

3
15.12.2008 11:54:48
Я позаботился о том, чтобы каждый новый указатель также удалялся. Мои журналы печати отладки показывают это по крайней мере. Есть ли в VS2003 какие-либо инструменты или автономные средства для поиска утечек?
Paul Baumer 15.12.2008 12:04:19
Прочитайте msdn.microsoft.com/en-us/library/x98tx3cf(VS.80).aspx , что может помочь. Вы также должны проверить, что любые новые объекты, которые выделяют ресурсы, должны быть освобождены в своих деструкторах, и что любой новый [] сопоставляется с delete [].
Adam Wright 15.12.2008 12:18:35
Я думал, что delete [] устарел и достаточно удаления.
Paul Baumer 15.12.2008 12:21:52
delete [] требуется всякий раз, когда вы используете new [] для выделения данных.
e.James 15.12.2008 12:25:42
Да, проблема не в том, чтобы использовать delete []. Я должен был сделать это более ясно в своем ответе, я думаю.
schnaader 15.12.2008 13:31:03

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

Библиотека времени выполнения Microsoft C пытается вернуть память обратно операционной системе, вызывая _heapmin_region вызов _heap_free_region или _free_partial_region, который вызывает VirtualFree для передачи данных в операционную систему. Однако, если целые страницы в соответствующем регионе не пусты, они не будут освобождены. Распространенной причиной этого является кэширование бухгалтерской информации и хранилища контейнеров C ++.

5
15.12.2008 12:06:05
Это может быть в случае с Java, но, безусловно, не в случае стандартных библиотек C / C ++ в Windows, по крайней мере, в отношении чего-либо большего, чем страница памяти. Попробуйте и убедитесь сами.
Tamas Czinege 15.12.2008 12:11:45
Вы правы. Я отредактировал ответ, чтобы описать, как Microsoft C обрабатывает освобождение.
Diomidis Spinellis 15.12.2008 12:24:06
Где вы можете прочитать такие подробности? Ссылка на MS или печатную книгу была бы отличной. Я искренне не знаю, где искать, и даже подозреваю, что искать некуда, и что люди узнают это экспериментально - надеюсь, что это не так!
JDiMatteo 10.11.2014 21:09:21
Вы можете найти эти детали в исходном коде! Вот как я нашел это, и это, как правило, единственный определенный источник правды.
Diomidis Spinellis 12.11.2014 08:22:24

Поскольку вы используете очень большие блоки памяти, вам следует рассмотреть возможность использования VirtualAlloc () и VirtualFree () , поскольку они позволяют вам выделять и освобождать страницы напрямую, без дополнительных затрат (в памяти и времени) на взаимодействие с менеджером кучи.

Поскольку вы используете C ++, стоит отметить, что вы можете создавать объекты C ++ в памяти, которую вы выделяете таким образом, с помощью размещения new .

1
15.12.2008 20:22:28

Эта проблема почти наверняка фрагментации памяти. В 32-битной Windows самый большой непрерывный регион, который вы можете выделить, составляет около 1,1 ГБ (поскольку различные библиотеки DLL в вашем EXE-файле препятствуют расширению непрерывного диапазона). Если после освобождения выделения памяти (или загрузки DLL, или файла отображения памяти) окажется в середине вашей предыдущей области 1 ГБ, то больше не будет области 1 ГБ, доступной для вашего следующего вызова new для выделения 1 ГБ. Таким образом, это не удастся.

Вы можете визуализировать этот процесс с помощью VM Validator .

1
10.04.2010 20:51:02