Деление на ноль вызывает утечку памяти в Borland C++
Я просто запускаю следующий код в Borland C++ Builder Version 6;
for (int i = 0; i < 40000; i++)
{
try {
__int64 n = 0;
__int64 r = 1 / n;
}
catch (Exception& e) {}
}
и во время выполнения этого цикла я вижу в диспетчере задач (столбец Память), что это утечка памяти. Есть идеи почему?
У меня была утечка памяти во время работы над вычислительным модулем в моем проекте, когда я пытался разделить на ноль, и после многочасового удара в голову, где утечка памяти, я понял, что это утечка памяти и в вышеупомянутом простом цикле. В проекте не было найдено никаких проблем.
2 ответа
Из стандарта 5/4 мы узнаем, что:
Если во время вычисления выражения результат не определен математически или не находится в диапазоне представляемых значений для его типа, поведение не определено.
Таким образом, поскольку деление на ноль математически не определено, поведение не определено. Неопределенное поведение включает в себя утечки памяти, поэтому на самом деле не стоит более подробно рассуждать о том, почему происходит утечка памяти (хотя такой инструмент, как valgrind, может помочь вам определить источник).
Диспетчер задач не является хорошим инструментом для тестирования утечек памяти. Он может только сообщить, сколько памяти было выделено процессом, но не то, как этот процесс использует память.
То, что вы не принимаете во внимание, это то, что менеджер памяти C++Builder кэширует освобожденную память, он не сразу возвращает ее в ОС. Вероятно, вы видите фрагментацию памяти, а не утечку памяти. Фрагментация может помешать менеджеру памяти повторно использовать уже кэшированную память, заставляя его выделять все больше и больше памяти ОС. Это может вызвать поведение, которое вы видите в диспетчере задач. Если вы смотрите диспетчер задач Page Faults
столбец, вы увидите, что это значение растет вместе с использованием памяти. Это хороший признак того, что память не используется повторно.
При этом менеджер памяти по умолчанию, используемый C++Builder 6, не был лучшим менеджером памяти. В более поздней версии он был заменен на FastMM, который также можно использовать в C++Builder 6. FastMM не страдает от фрагментации памяти.