Утечка памяти в сборщике мусора .NET с помощью System.Transactions.SafeIUnknown - PullRequest
1 голос
/ 04 марта 2010

Я пытаюсь отследить утечку памяти в приложении, используя профилировщик ANTS. Я отследил его до сборщика мусора, где у нас есть список объектов System.Transactions.SafeIUnknown, которые постоянно находятся в сборщике мусора, находятся в очереди финализатора, но никогда не освобождаются.

Я не могу найти документацию о System.Transactions.SafeIUnknown, а также не могу определить, что будет создавать или ссылаться на нее, с нашей стороны это не преднамеренно.

Я надеюсь, что кто-то там может иметь некоторые знания об этом. Это небольшая утечка в 20 байт, но когда наши приложения работают целыми днями, утечка накапливается, и у нас есть миллионы таких ожидающих завершения, и она начинает поглощать много-много памяти.

Кто-нибудь есть идеи, куда идти?

Последующий

Я отследил его до определенной используемой библиотеки. Кажется, что он остается позади после того, как мы выполним любые операторы SQL через эту конкретную библиотеку. Состояния не заключаются в транзакции, но они выполняются с помощью довольно сложного цикла, универсальных типов и того, что в настоящее время выглядит как двойная тройная косвенность с делегатами, передаваемыми для спорта и заключенными в замыкания, которые можно заключить в большее число замыканий. Я буду продолжать пытаться точно связать его, мой первый порт захода - попытаться выяснить, смогу ли я воспроизвести его, используя аналогичный механизм.

Ответы [ 2 ]

4 голосов
/ 04 марта 2010

SafeIUnknown является производным от SafeHandle. Это класс, который реализует финализатор. Он особенный, его код завершения выполняется в критической области выполнения (CER). Такой код обеспечивает гарантию выполнения, исключения исключаются. Финализатор запускает SafeIUnknown.ReleaseHandle (), он вызывает Marshal.Release () для освобождения указателя COM-интерфейса, заключенного в SafeIUnknown.

Просмотр множества этих оболочек в очереди завершения указывает на то, что вызов Marshal.Release () вызывает исключение. Предотвращение завершения оболочки. Выяснить, почему именно оно создает исключение, будет сложно. Это неуправляемая бомбардировка кода, у вас будет несколько подсказок, чтобы узнать почему. 95% случаев - это повреждение кучи, очень сложная проблема для устранения. Прежде всего потому, что это, вероятно, не ваш код и у вас нет источника.

Вы должны иметь возможность получить точку останова в хорошем отладчике неуправляемого кода (например, WinDbug) при исключении первого шанса. Получение отладочных символов имеет важное значение для понимания любого вида трассировки стека. Это, однако, вероятно, будет еще далеко. Подумайте о получении помощи от службы поддержки Microsoft. Или что-то радикальное, как восстановление машины. Удачи с этим!

1 голос
/ 04 марта 2010

SafeIUnknown происходит от нескольких методов в System.Transactions, одним из которых являются конструкторы TransactionScope и метод Dispose. Вызовы этих методов заканчиваются внутренним методом класса Transaction с именем JitSafeGetContextTransaction, который далее вызывает собственную функцию Ole32 CoGetDefaultContext, которая возвращает экземпляр SafeIUnknown.

Это указывает на то, что рассматриваемый объект связан с внутренним представлением контекста вашей транзакции.

Может быть, вы неправильно освобождаете транзакции или области транзакций? Если так, возможно, есть какая-то проблема с поставщиком данных, который вы используете?

...