Каковы часто встречающиеся причины утечек памяти COM? - PullRequest
4 голосов
/ 16 ноября 2009

Каковы наиболее часто встречающиеся причины утечек памяти COM?

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

Ответы [ 3 ]

7 голосов
/ 16 ноября 2009

Отказ от использования типов оболочки RAII для COM-объектов. В частности, не используются CComPtr<>, CComBSTR и CComVARIANT<>. Эти объекты помогают предотвращать утечки, снимая с себя ответственность за освобождение основного ресурса от разработчика. Объект-оболочка обеспечивает освобождение ресурсов в своем деструкторе.

Другой причиной утечек или случайных освобождений, которые я видел, является результат неявного преобразования из CComPtr<T> в T*. Это полезно для передачи обернутых объектов в качестве аргументов. Но это может вызвать проблемы, поскольку допускает неявное преобразование между объектом RAII и необработанным указателем. Например

CComPtr<IFoo> GetAFoo();  // Imagine if this creates the object
...
IFoo* pFoo = GetAFoo();   
pFoo->SomeCall();  

В этом сценарии вызов SomeCall, скорее всего, завершится неудачей, поскольку объект pFoo в этот момент мертв. Зачем? Значение было возвращено со счетчиком ссылок 1 из GetAFoo, присвоено pFoo, затем уменьшено до 0 и удалено, поскольку временное значение выпало из области видимости.

4 голосов
/ 16 ноября 2009

Забыть для вызова Release (), когда вы должны. Используйте CComPtr <>, CComVARIANT <> и CComBSTR, чтобы помочь вам.

2 голосов
/ 17 ноября 2009

Есть две основные причины: не использовать RAII (умные указатели) и неправильно использовать RAII.

Если вы используете необработанные указатели - IInterface * или BSTR, вы рискуете забыть вызвать IInterface :: Release () или SysFreeString (), и это приведет к утечке. Если вы используете умные указатели неправильно, вы также рискуете утечки памяти. Один из способов сделать это - тот, который вы упомянули - передать инициализированный CComBSTR :: operator & () в качестве параметра [out]. Существуют и другие способы, такие как передача CComPtr :: operator & () или CCOmQIPtr :: operator & () инициализированного интеллектуального указателя в качестве параметра [out] с отключенными ATLASSERT. Или создайте любую графоподобную структуру с циклом и полностью освободите ее, чтобы каждый объект в цикле удерживал интеллектуальные указатели друг на друге и предотвращал освобождение.

...