2016-07-05 4 views
0

Когда я создаю пустое консольное приложение и использую в нем контейнер STL, FastMM сообщает об утечке памяти при закрытии приложения.FastMM сообщает об утечках памяти в контейнерах STL в C++ Builder 6

Например, если я создаю std::vector<int> в main():

std::vector<int> v; 

компилировать, запускать и близко, не сообщается никаких утечек.

Если я:

std::vector<int> v; 
v.push_back(100); 

я получаю:

Это приложение утечка памяти. Небольшие утечки блоки:

309 - 340 байт: Unknown х 1

Кроме того, я получаю утечку сообщил:

std::vector<int> v; 
v.push_back(100); 
v.clear(); 

А также утечка сообщается на:

std::vector<int> v; 
v.reserve(1); 

Для некоторых контейнеров, таких как std::deque, его достаточно просто создать, и даже без изменения его содержимого утечка представляет собой rep если приложение закрыто.

Может ли кто-нибудь объяснить, что происходит? Я использую Borland C++ Builder 6 и FastMM4. Я меняю различные настройки в FastMMOptions.inc, однако я все еще вижу, что эти утечки сообщаются.

+3

[Borland C++ Builder 6] (https://en.wikipedia.org/wiki/C%2B%2BBuilder#Version_history), похоже, вышел в 2002 году .... любой шанс вы могли бы использовать более современный компилятор? Даже более поздняя версия C++ Builder? 14 лет - долгое время в программном обеспечении. – CoryKramer

+0

Я говорю, потому что, учитывая этот фрагмент кода, нет ничего, что могло бы вызвать утечку памяти (не видя окружающего контекста), кроме компилятора, вместо ошибочной реализации «std :: vector». Или ложный сигнал, обнаруженный детектором утечки. – CoryKramer

+0

Да, у нас есть Borland XE7, и новые проекты разрабатываются в новой среде. Однако мне нужно исследовать утечки памяти в существующих проектах, которые мы еще не перенесли на XE7 из-за их размера. Я считаю, что FastMM очень полезен, но поскольку STL используется во многих местах нашего кода, он указывает на течи, которые меня очень путают. – bboydushko

ответ

1

очищающих std::vector не освобождает память, используемую для внутреннего массиву vector «s, она просто разрушает элементы внутри массива, а затем устанавливает std::vector::size() 0. Сам массив еще выделяется, поэтому он может быть использован повторно для новых предметы, нажатые в vector. Деструктор vector освободит массив.

В C++ Builder 6 стандартная библиотека STL представляет собой STLPort (заменена Dinkumware в C++ Builder 2006). Выполнение STLPort ~std::vector() просто разрушает элементы массива (как если бы вызывался clear()), но не освобождает сам массив, таким образом, вы видите «утечку». Что на самом деле не утечка на всех, в соответствии со следующей FAQ на сайте STLPort:

Q6.2 My tool detect memory leaks in application with STLport. Is this leak from STLport?

A6.2 В большинстве случаев это являются «утечки памяти псевдо», что некоторые инструменты ошибочно поддерживает.

В сборке по умолчанию STLport распределитель узлов используется для выделения внутренней памяти. Распределитель узлов работает, предварительно выделяя большой кусок памяти и выдавая небольшие блоки памяти. Блок памяти не освобождается во время запуска приложения, которое использует STLport (т.е. оно не возвращается в систему. Существуют такие инструменты, как BoundsChecker, Purify или Valgrind, которые проверяют утечки памяти, для памяти, которая не освобождается, когда больше не используется . Эти инструменты могут сообщать о ложных утечках памяти, когда используется распределитель узлов STLport.Блок памяти обычно освобождается в конце приложения, но контролеры памяти обычно сообщают об утечке памяти до этой точки. Другая проблема с памятью может быть сообщена при использовании разделяемых библиотек (например, DLL, эта проблема, характерная для модели Windows DLL), которая использует STLport внутри себя и статически ссылается на нее. Если память выделена в dll и выпущена в другой, то распределитель узла STLport сохранит выпущенную память для будущего использования. Если вы не используете эту память, ваше потребление глобальной памяти вашего приложения будет расти до тех пор, пока аппликация не произойдет, даже если нет реальной утечки памяти. Вот почему вы всегда должны использовать согласованную конфигурацию все в dll или все в статическом lib.

Есть способы удалить утечки псевдопамяти (поскольку память правильно освобождена в конце программы, утечки являются просто псевдо-одними). Вы можете использовать другой распределитель, который используется в STLport. Откройте файл "stlport/stl/_site_config.h" и раскомментируйте либо один из следующих действий:

_STLP_USE_NEWALLOC enables a simple allocator that uses "new/delete" 
_STLP_USE_MALLOC  enables a simple allocator that uses "malloc/free" 

нового/удалить Распределитель имеет преимущество дает точку входа для отслеживания голодания памяти см set_new_handler в вашем компиляторе документе или Standard на C++ для получения дополнительной информации ,

В качестве альтернативы вы можете определить следующий символ, просто раскомментируйте его в "stlport/stl/_site_config.h".

_STLP_LEAKS_PEDANTIC 

Символ заставляет освобождать все куски памяти. Также см. Комментарии вокруг символа в файле конфигурации.

Обратите внимание, что при внесении любых изменений в файл вам необходимо перекомпилировать STLport И ваше приложение и все ваши зависимые библиотеки!

Есть также некоторые определения, которые помогают отлаживать проблемы с памятью в STLport. В режиме _STLP_DEBUG, как раз и определяют следующие символы, либо в «./stlport/stl_user_config.h» или в настройках проекта:

_STLP_DEBUG_ALLOC 
_STLP_DEBUG_UNINITIALIZED   

Вам не нужно перестраивать STLport для этих вариантов, но у вас есть перестроить ваше приложение и все ваши зависимые библиотеки, если вы внесете какие-либо изменения в файл.

Тем не менее, RogueWave STL, который использовался в более ранних версиях C++ Builder, также поставляются с C++ Builder 6 для обратной совместимости с более старой кодой, и не страдает от этой проблемы. Вы можете переключиться с STLPort на RogueWave, указав _USE_OLD_RW_STL в списке условных обозначений вашего проекта.

+0

Отлично, и очень информативный ответ. Определяя '_USE_OLD_RW_STL', FastMM не сообщает о утечках в контейнерах, используемых в нашем проекте (' std :: vector' 'std :: list'' std :: deque'). Большое спасибо. Теперь гораздо легче просмотреть отчет об утечке памяти. – bboydushko

+0

Еще одна вещь, которую я заметил, любое использование 'std :: cout' также сообщает об утечке. К счастью, в нашем коде не так много, но если вы знаете другое «волшебное условное определение», чтобы остановить появление в отчете, это было бы здорово. Пример: 'std :: cout <<" hello "<< endl;' reports: 13 - 20 bytes: Неизвестно x 1 21 - 36 bytes: std :: codecvt x 1 , Неизвестно x 2 37 - 52 bytes: Неизвестно x 2 53 - 68 bytes: std :: ctype x 1, __rwstd :: locale_imp x 2 85 - 100 bytes: Неизвестно x 2 485 - 532 байт: Неизвестно x 3 , в то время как 'printf (" hello \ n ");' не сообщает утечки – bboydushko