Реферат: Перехват методов COM интерфейсов

Эти соглашения о вызовах в первую очередь различаются тем, кто ответственен за удаление параметров из стека после вызова. stdcall-функции очищают стек сами, а для cdecl-функций стек очищает вызывающая функция.

Подход ATL

В библиотеке ATL перехват вызовов используется для отладки COM-серверов. Если до включения заголовочного файла <atlbase.h> объявить символ препроцессора _ATL_DEBUG_INTERFACES (или _ATL_DEBUG_REFCOUNT), то в окне “Output” отладчика VS во время выполнения приложения будут появляться сообщения, описывающие вызовы AddRef и Release для COM-объектов, созданных с помощью ATL, текущий счетчик ссылок или IID запрашиваемого интерфейса. Ниже приведен пример таких сообщений:

QIThunk-1 AddRef:Object=0x00da4c50 Refcount = 1 CComClassFactory - IUnknown

QIThunk-2 AddRef:Object=0x00da4c50 Refcount = 1 CComClassFactory - IClassFactory

QIThunk-3 AddRef:Object=0x00da4e20 Refcount = 1 CFoo - IFoo

QIThunk-3 AddRef:Object=0x00da4e20 Refcount = 2 CFoo - IFoo

QIThunk-3 Release:Object=0x00da4e20 Refcount = 1 CFoo - IFoo

QIThunk-2 Release:Object=0x00da4c50 Refcount = 0 CComClassFactory - IClassFactory

QIThunk-4 AddRef:Object=0x00da4e20 Refcount = 1 CFoo - IFoo

QIThunk-3 Release:Object=0x00da4e20 Refcount = 0 CFoo - IFoo

QIThunk-1 Release:Object=0x00da4c50 Refcount = 0 CComClassFactory - IUnknown

ATL: QIThunk-4 LEAK:Object = 0x00da4e20 Refcount = 1 MaxRefCount = 1 CFoo - IFoo

Во время выгрузки ATL COM-сервера в окне “Output” появятся сведения об указателях на интерфейс, для которых счетчик ссылок не достиг значения 0, т.е. об утечках COM объектов.

“Магия” ATL работает благодаря перехвату вызовов методов COM-интерфейсов, в частности, AddRef, Release и QueryInterface.

Когда клиент запрашивает интерфейс у объекта с помощью QueryInterface, класс CComObject делегирует вызов базовому классу CComObjectRootBase::InternalQueryInterface, который при определенном макросе _ATL_DEBUG_INTERFACES обращается к экземпляру класса CAtlDebugInterfacesModule и вызывает у него метод AddThunk.

HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw()

Результатомвызова CComObjectRootBase::InternalQueryInterface становитсяспециальныйобъект-посредник QIThunk, которыйперехватывает AddRef, Release и QueryInterface, авсеостальныевызовыделегируетисходномукомпоненту.

Класс CAtlDebugInterfacesModule хранит список всех активных объектов-заместителей QIThunk и в своем деструкторе выполняет отладочную печать всех объектов, чей счетчик ссылок не достиг нулевого значения.

Когда клиент отпускает последнюю ссылку на компонент, QIThunk удаляет себя из списка активных посредников в CAtlDebugInterfacesModule.

Таким образом, клиенты имеют дело не с прямым указателем на интерфейс COM-объекта, а с указателем на QIThunk, который и печатает отладочные сообщения о текущем значении счетчика ссылок и IID запрашиваемого интерфейса.

Указатель на QIThunk ведет себя в точности так же, как и указатель на обычный интерфейс. Это достигается за счет того, что vtbl класса QIThunk содержит адреса методов-перехватчиков, вызывающих исходные методы. Поскольку все интерфейсы унаследованы от IUnknown, первые три адреса vtbl содержат QueryInterface, AddRef и Release. Их реализация в QIThunk тривиальна – сигнатура методов в точности известна на этапе компиляции.

Но как быть с остальными методами интерфейса, количество и сигнатуры которых неизвестны? Для решения этой проблемы QIThunk использует универсальную функцию-перехватчик, адресом которой заполняется vtbl. Виртуальные методы объявляются в QIThunk так:

STDMETHOD(f3)();

STDMETHOD(f4)();

...

STDMETHOD(f1023)();

Vtbl QIThunk содержит 1024 адреса. Интерфейсы, объявляющие большее количество методов, встречаются нечасто.

Реализация этих методов задается с помощью макроса:

ATL_IMPL_THUNK(3)

К-во Просмотров: 665
Бесплатно скачать Реферат: Перехват методов COM интерфейсов