Visual Studio 2017 - инструмент Diagostic - профилирование кучи влияет на потребление памяти программой
Я пытаюсь отладить странную утечку памяти в приложении C# (использует C++/cli и C++) с помощью инструмента диагностики и снимков памяти. Но я обнаружил одну странную проблему.
Когда я запускаю отладку в VS2017 с включенным профилированием кучи, потребление памяти остается постоянным, и программа работает, как и ожидалось. Когда профилирование кучи выключено, программа пропускает память, которая имеет линейное увеличение. Выполненная работа такая же, у меня есть прогресс работы, напечатанный на консоли, и я уверен, что обе программы выполнили одну и ту же работу, но одна использует постоянную память, а другая имеет линейно увеличивающуюся память (когда та же самая работа сделана, 2x использованная память). Визуально это выглядит так, что когда GC запускается с помощью профилирования кучи, освобождается какая-то память, а при использовании профилирования кучи память не освобождается.
Кто-нибудь имеет представление, как это может повлиять на профилирование кучи? Родная память просочилась.
[EDIT1] Данные из Performance Profiler -> Использование памяти
Object Type Reference Count Module
shared_ptr_cli<GeoAtomAttributes> TestBackEnd64.dll
shared_ptr_cli<GeoAtomAttributes> [Finalization Handle] 856,275 TestBackEnd64.dll
shared_ptr_cli<GeoAtomAttributes> [Local Variable] 1 TestBackEnd64.dll
GeoAtomAttributesCli [Local Variable] 1 TestBackEnd64.dll
1 ответ
Память, которая может быть связана с gc, не должна рассматриваться как утечка памяти, она должна рассматриваться как память, подходящая для сбора мусора. Поскольку при следующем выполнении gc эта память будет собрана и доступна для размещения новых объектов.
Другие мысли;
Gc работает в управляемой куче, собственные библиотеки распределяют память в собственной куче. Так что это не может повлиять на управление памятью нативных библиотек. Но вы должны знать о следующих случаях.(Возможно, это не ваш случай)
Если вы передаете закрепленные структуры данных в собственный код и освобождаете эти дескрипторы в своем методе Object.Finalize (класса-оболочки); в этом случае закрепленная память может быть собрана только тогда, когда класс-оболочка находится в очереди для финализации. Вызов функций очистки (*) собственного кода в методе finalize управляемого класса также может вызывать аналогичные случаи. Я думаю, что это плохие практики и не должны использоваться, вместо этого эти очистки должны быть сделаны как можно скорее.
(*) В этом случае может увеличиться общее потребление памяти процессом, даже если в управляемой куче нет необходимости в gc.