Реферат: Перехват методов 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 интерфейсов
|