Требуется ли для справок COM Dll утилизация вручную? Если так, то как? - PullRequest
2 голосов
/ 01 июня 2010

Я написал некоторый код на VB, который проверяет, что определенный порт в брандмауэре Windows открыт, и открывает его в противном случае. Код использует ссылки на три библиотеки COM DLL. Я написал класс WindowsFirewall, который импортирует основное пространство имен, определенное библиотеками DLL. Внутри членов класса WindowsFirewall я создаю некоторые типы, определенные в библиотеках DLL, на которые ссылаются. Следующий код не весь класс, но демонстрирует, что я делаю.

Imports NetFwTypeLib
Public Class WindowsFirewall
    Public Shared Function IsFirewallEnabled as Boolean
        Dim icfMgr As INetFwMgr
        icfMgr = CType(System.Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwMgr")), INetFwMgr)

        Dim profile As INetFwProfile
        profile = icfMgr.LocalPolicy.CurrentProfile

        Dim fIsFirewallEnabled as Boolean
        fIsFirewallEnabled = profile.FirewallEnabled

        return fIsFirewallEnabled
    End Function
End Class

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

(Моя теория состоит в том, что объекты icfMgr и profile выделяют память, которая остается невыпущенной до закрытия приложения. Я надеюсь, что установка их ссылок равными нулю пометит их для сборки мусора, так как я не могу найти другого способа избавьтесь от них. Ни один из них не реализует IDisposable, и ни один из них не содержит метод Finalize. Я подозреваю, что они могут даже не иметь отношения здесь, и что оба эти метода освобождения памяти применимы только к типам .Net.)

Ответы [ 2 ]

2 голосов
/ 02 июня 2010

Не уверен, что рекомендовать здесь. Здесь определенно нет утечки памяти, сборщик мусора выпускает счетчики ссылок COM. COM-объекты не являются одноразовыми, но вы можете освободить их раньше с помощью Marshal.ReleaseComObject (). Проблема с этим явно заключается в том, что обычно очень трудно отслеживать ссылки на интерфейсы.

Например, в вашем фрагменте кода вызов ReleaseComObject для icfMgr не будет иметь никакого эффекта. Через элемент LocalPolicy есть скрытая ссылка, которая будет поддерживать ссылку на интерфейс живым. Вам также придется вызывать ReleaseComObject для этой скрытой ссылки.

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

0 голосов
/ 01 июня 2010

Вы совершенно правы: неуправляемый код не может управляться и, следовательно, должен управляться вручную: уничтожен. Тем не менее, это во многом зависит от того, что вы делаете, но во многих случаях достаточно обернуть экземпляр объекта вокруг блока Using. Это работает только если вы используете объект, который реализует IDisposable.

Однако, как вы сейчас создаете экземпляр COM-объекта, у вас не будет возможности легко его очистить. Это зависит от объекта. Когда он не нуждается в очистке (проверьте деструктор FwMgr), он также не нуждается в утилизации. Однако большинство объектов COM нуждаются в удалении.

Итак, как добавить интерфейс IDisposable к COM-объекту, который изначально не поддерживает его? Это немного трудоемко сделать вручную, но вы должны создать сборку оболочки .NET. К счастью, работа была взята из наших рук, и Microsoft создала некоторые инструменты и рекомендации .

Часть этой информации также описана здесь . Вы можете также поискать WeakReference в качестве альтернативы.

Обратите внимание, что COM и .NET плохо общаются друг с другом, но общаются. Отличным справочником является .NET и COM Полное руководство по взаимодействию от Don Box, SAMS Publishing.

EDIT:
В ответ на ваш вопрос «утечки памяти»: невозможно сказать, ввели ли вы утечку памяти и насколько она велика. Это зависит от того, как часто вы вызываете свой COM-объект. Вызовите это один раз за запущенный процесс? Не волнуйся слишком сильно. Назовите это сотыми разами во внутреннем цикле? Будь очень осторожен. Хотите знать наверняка? Поиск оригинальной документации или источника: если он освобождает дескрипторы, память или другие ресурсы, когда он разрушен, тогда да, вы допустили утечку.

...