Утечка памяти или фрагментация памяти?

Я запускаю следующий код в Borland Builder C++ 6 и вижу увеличение памяти, используемой программой в Memory (Private Working Set) диспетчере задач Windows, что, я считаю, является утечкой памяти.

for (int i = 0; i < 100000; i++)
{      
   try {
     int n = 0;
     int r = 1 / n; //division by zero
   }
   catch (EDivByZero& e) {}
}

Я попытался заменить диспетчер памяти Builder C++ по умолчанию на FASTMM4, но вижу то же поведение. Это из-за утечки памяти или фрагментации памяти, потому что я путаюсь между ними. Я считаю, что в обоих случаях программа должна выгружать виртуальную память на диск, что увеличивает используемую память.

Глядя на виртуальную память, можно провести различие между утечкой и фрагментацией, но как это сделать? Есть ли инструмент в Windows для проверки?


person nommyravian    schedule 20.09.2013    source источник
comment
Я попробовал код в BCB2010, и память процесса совсем не увеличилась.   -  person mh taqia    schedule 20.09.2013
comment
Спасибо, что протестировали его, и вот в чем мой вопрос; если это проблема в BCB6, а RTL/FASTMM не освобождает память, используемую для исключения.   -  person nommyravian    schedule 20.09.2013
comment
Я использовал FastMM с BCB6, и у него тоже была утечка памяти. Я проверил с помощью отчетов FastMM.   -  person nommyravian    schedule 23.09.2013


Ответы (1)


«увеличение памяти, используемой программой в памяти (частный рабочий набор) диспетчера задач Windows, что, я считаю, является утечкой памяти». - Это неправильно

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

Примечание. Это только типичное поведение, С++ ничего не говорит об этом явно, YMMV.

person john    schedule 20.09.2013
comment
Я вообще-то говорю об увеличении используемой программой памяти в диспетчере задач только во время этого цикла. Когда цикл начинается, это 1,580K и достигает 5,880K. Это также увеличивает количество ошибок страницы. Цикл, имеющий любую другую арифметическую операцию, этого не делает. - person nommyravian; 20.09.2013
comment
Ладно, думаю, механизм исключений в Borland выделяет память (что неудивительно). Однако это не приводит к утечке памяти. - person john; 20.09.2013
comment
Что ж, ты прав. Я протестировал его, вызвав какое-то другое исключение, и он ведет себя так же, но когда я использую e.Free() в блоке catch, он не увеличивает используемую память. Означает ли это, что мы очищаем используемую память в виде исключения? Если да, то почему Borland этого не делает? - person nommyravian; 20.09.2013
comment
а также каждый раз, когда я запускаю цикл, он всегда увеличивает память, используемую программой. Зачем каждый раз нужна новая память? Не потому ли, что Builder C++ каким-то образом не освобождает память, используемую по исключению, и каждый раз нуждается в новой памяти, или это фрагментация памяти? - person nommyravian; 20.09.2013
comment
Когда вы освобождаете память в своей программе, она будет освобождена обратно в вашу программу, а не в ОС: это правильно. - person mh taqia; 20.09.2013
comment
Здесь вы находитесь в поведении, определенном реализацией. Я был бы удивлен, если бы вы явно освобождали память для объектов-исключений, но если Borland так спроектировала вещи, вам придется с этим смириться. - person john; 20.09.2013
comment
@mhtaqia Не могли бы вы уточнить? - person john; 20.09.2013
comment
Справочная документация запрещает вызывать Free() напрямую, но сама borland не освобождает его. Я застрял с исходным кодом borland VCL (Delphi) в поисках причины. - person nommyravian; 20.09.2013
comment
@john Если освобожденная память не возвращается в ОС, мы освобождаем выделенную память для Почему? - person mh taqia; 20.09.2013
comment
@mhtaqia Так что ваша программа может использовать его повторно. Описанная мной ситуация нормальная. Освобожденная память не возвращается ОС, но может быть повторно использована программой. Но, как я уже сказал, детали варьируются от ОС к ОС и от программы к программе. Все, что я на самом деле хочу сказать, это то, что если вы освобождаете память, вы не можете гарантировать, что память будет доступна для другого процесса. Это гарантируется только тогда, когда ваш процесс завершается. - person john; 20.09.2013
comment
Освобождение перехваченного исключения вручную НЕПРАВИЛЬНО. Период. Не делай этого. RTL владеет памятью, а не вы. Исключения на основе VCL размещаются в куче, и RTL отвечает за освобождение перехваченных исключений после выхода из блока catch. А RTL BCB делает освобождение от перехваченных исключений. Таким образом, все, что вы испытываете, скорее всего, НЕ является утечкой памяти, но вы можете использовать возможности утечки памяти FastMM, чтобы проверить это, поскольку он знает все, что он выделяет, и сообщит вам, если какая-либо выделенная память не была освобождена. - person Remy Lebeau; 21.09.2013
comment
И, кстати, НЕ используйте Free() в C++. Это только для использования в Delphi. Вместо этого используйте оператор C++ delete. - person Remy Lebeau; 21.09.2013
comment
@RemyLebeau это утечка памяти. Я только что протестировал его с отчетом FastMM4. Теперь, когда происходит утечка памяти при каждом исключении EDivByZero, EAccessViolation или подобных, должны ли мы просто жить с этим или освобождать его в блоке catch, коде C++? Почему бы нам не освободить его? - person nommyravian; 23.09.2013
comment
Я уже говорил это несколько раз. Вы НЕ МОЖЕТЕ напрямую освободить перехваченное исключение, если только вы не являетесь тем, кто непосредственно выделил его в куче, а затем бросил. В случае исключений VCL вы НЕ владеете памятью для них, а владеете RTL. Ответственность за их освобождение лежит на RTL. Если RTL пропускает исключения VCL, то в RTL есть ошибка. С учетом сказанного, я сам использую BCB6, и у меня никогда не было проблем с утечкой RTL перехваченных исключений VCL. С учетом сказанного, простой ответ заключается в том, чтобы в первую очередь не вызывать исключения. Проверьте свой ввод на 0 перед делением и т. д. - person Remy Lebeau; 23.09.2013