MSXML get_documentElement () и возврат указателей на интерфейсы COM - PullRequest
0 голосов
/ 21 января 2012

Мне было интересно, является ли обычной практикой в ​​COM-библиотеках вызывать Addref через COM-интерфейс, который возвращается из функции.Например:

IXMLDOMElement* domElement = NULL;
document_->get_documentElement(&domElement);  // does get_documentElement() call Addref on domElement?
// ...
// do something with domElement
// ..
domElement.Release(); // correct?
// (btw. member variable document_ is of type CComPtr<IXMLDOMDocument2>

или с умным указателем:

CComPtr<IXMLDOMElement> domElement;
document_->get_documentElement(&domElement);

Кстати.Я обнаружил, что в документах MSXML для «Windows Media 9 Series» говорится, что Addref называется: http://msdn.microsoft.com/en-us/library/ms751196(v=vs.85).aspx

Но в официальной документации об этом ничего не сказано: http://msdn.microsoft.com/en-us/library/ms759095(v=vs.85).aspx

Ответы [ 2 ]

2 голосов
/ 21 января 2012

Функция, которая возвращает указатель интерфейса, должна вызывать AddRef() перед выходом, а не функцию, которая получает объект. Функция, которая получает указатель интерфейса, должна использовать его как есть и затем вызывать Release() для него. Это означает, что get_documentElement() будет звонить AddRef(), поэтому не называйте это сами.

Правила для того, кто - звонящий или вызываемый - отвечает за то, что делать в отношении подсчета ссылок и управления памятью в COM, четко определены в документации COM на MSDN:

Правила объектной модели компонентов

Правила подсчета ссылок

2 голосов
/ 21 января 2012

Да, вы должны вызвать addref перед возвратом COM-объекта, поскольку у вызывающей стороны будет новый указатель интерфейса, ссылающийся на объект, поэтому счетчик ссылок должен быть увеличен на единицу. Это правило, а не исключение.

Однако документирование внутреннего адреса является исключением, поскольку подсчет ссылок является одной из основ COM. Вероятно, документация была написана, когда многие пользователи этого метода не знают правила и вызвали слишком много утечек памяти.

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

...