Как отследить источник вывода утечки памяти CRT от управляемого C# кода? - PullRequest
3 голосов
/ 22 января 2020

Я использую программное обеспечение, написанное на C# (WPF), в котором используется много собственного устаревшего кода. Когда я закрываю программное обеспечение, отладчик продолжает работать, и мой экран вывода отладки печатает это:

Detected memory leaks!
Dumping objects ->
{41198} normal block at 0x00000211F11C58F0, 16 bytes long.
 Data: <                > D8 CE DF B0 8D 00 00 00 00 00 00 00 00 00 00 00 
{41194} normal block at 0x00000211C66AD710, 96 bytes long.
 Data: <D:\mydir\somedir> 44 3A 5C 72 65 70 6F 5C 69 71 73 2D 74 72 75 6E 
{41193} normal block at 0x00000211F11C5210, 16 bytes long.
 Data: <                > 80 83 A1 E1 11 02 00 00 00 00 00 00 00 00 00 00 
{41192} normal block at 0x00000211E1A18360, 88 bytes long.
 Data: <                > 90 80 9D E0 11 02 00 00 90 80 9D E0 11 02 00 00 
(Repeated)

(я изменил путь, который там показан, на «mydir \ somedir»)

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

Программное обеспечение использует множество библиотек, написанных на C и C ++. Существует несколько проектов C ++ / CLI, которые работают как оболочки и используются кодом C#.

У меня есть доступ к используемому исходному коду, поэтому я запустил поиск всех определений _CRTDBG_MAP_ALLOC и переопределил оператор new , как описано в MSDN , но выходные данные остались прежними и не отображали информацию о строках / файлах. Я даже не уверен, что это происходит из нашего кода.

Как я могу отследить источник этой утечки памяти? Есть ли способ хотя бы определить, какой файл / проект вызывает это? Предполагая, что это исходит из нашего кода, есть ли способ использовать код C ++ / CLI для отладки этого?

1 Ответ

5 голосов
/ 23 января 2020

Проблема была на самом деле в оболочках C ++ / CLI.

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

Однако оказывается, что G C не вызывает деструктор, скорее он вызывает финализатор .

Решением было переместить весь код из деструкторов в финализаторы, и после этого ни одна строка дампа не отображается в выходные данные отладки, когда я закрываю программу, и память освобождается, когда G C работает и класс считается мертвым.

...