Первый раз в жизни нужно сделать класс как СОМ объект. Интерфейсы для объекта находятся в RTC API (VOIP). Интерфейсы имеют следующую иерархию наследования: IRTCPortManager3->IRTCPortManager2->IRTCPortManager->IUnknown. Все абстрактные функции, указанные в IRTCPortManager3, IRTCPortManager2 и IRTCPortManager, в моем классе реализованы, без этого были ошибки компиляции. Для интерфейса IUnknown, который тоже содержит несколько абстрактных функций, я ничего не писал, но компилятор не ругается. Никаких данных для класса в интерфейсах не объявлено.
Проблема заключается в том, что при попытке создания моего класса и по CComObject и по new вылетает "access violation" — попытка доступа по адресу 0. Вероятно класс должен содержать какие-то поля данных. Вопрос — какие? Я объявляю класс так как в имеющихся примерах, и никакие данные в примерах не объявляются. Подскажите, где проблема.
Объявление моего класса:
class ATL_NO_VTABLE MyPortManager : public CComObjectRootEx<CComMultiThreadModel>, public IRTCPortManager3 {
protected:
private:
public:
MyPortManager();
~MyPortManager();
.
. — методы из интерфейсов IRTCPortManager3, IRTCPortManager2 и IRTCPortManager — все пока заглушки
.
Здравствуйте, Alex1000000, Вы писали:
A>Проблема заключается в том, что при попытке создания моего класса и по CComObject и по new вылетает "access violation" — попытка доступа по адресу 0.
Вот и покажи код создания твоего класса.
A>Вероятно класс должен содержать какие-то поля данных. Вопрос — какие? Я объявляю класс так как в имеющихся примерах, и никакие данные в примерах не объявляются.
В классе, тобой объявленным, достаточно данных, чтобы быть СОМ объектом.
Здравствуйте, Vi2, Вы писали:
Vi2>Вот и покажи код создания твоего класса.
Какой код?
В моем коде сейчас все функции — заглушки, конструктор — пустой. Реальный код создания класса сидит где-то в ATL. И этот код, вероятно, ищет переменную типа RefCounter или какой-то указатель, какие-то данные, которые должны быть объявлены в СОМ объекте по умолчению, но я о них не знаю, поэтому они и не объявлены. Может нужно включить еще кого-то в родители?
"access violation" вылетает именно из этой строки: hr = CComObject<MyPortManager>::CreateInstance(&pMyPortManager);
Из нее программа уже не выходит как нужно, а попадает сразу в ловушку __except. Возможности отладки у меня ограничены текстовым логом и по логу я вижу, что вызывается мой конструктор (пустой) и затем сразу сообщение из __except.
Здравствуйте, Alex1000000, Вы писали:
A>"access violation" вылетает именно из этой строки: hr = CComObject<MyPortManager>::CreateInstance(&pMyPortManager); A>Из нее программа уже не выходит как нужно, а попадает сразу в ловушку __except. Возможности отладки у меня ограничены текстовым логом и по логу я вижу, что вызывается мой конструктор (пустой) и затем сразу сообщение из __except.
Такого поведения я не понимаю. Смотрим в код CComObject<MyPortManager>::CreateInstance:
HRESULT WINAPI CComObject<Base>::CreateInstance(CComObject<Base>** pp)
{
ATLASSERT(pp != NULL);
HRESULT hRes = E_OUTOFMEMORY;
CComObject<Base>* p = NULL;
ATLTRY(p = new CComObject<Base>())
if (p != NULL)
{
p->SetVoid(NULL);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalFinalConstructRelease();
if (hRes != S_OK)
{
delete p;
p = NULL;
}
}
*pp = p;
return hRes;
}
После конструктора CComObject<MyPortManager>() идет вызов функции SetVoid(NULL). Можно переопределить эту функцию в классе MyPortManager или/и FinalConstruct(), чтобы убедиться, что конструктор отработал. Есть, правда, ответвление в конструкторе CComObject() на вызов _Module.Lock() с возможным вылетом, но там негде вылетать. Резюме: СОМ и АТЛ тут как бы не причем. Возможно, тут причем настройки студии.
PS
Еще можно было бы заменить CComObjectRootEx<CComMultiThreadModel> на CComObjectRoot, которая учитывает апартмент компонента.
PPS
Если будет дополнительная информация, можно дальше подумать, почему вылетает. Пока остается руками развести.
Vi2>Если будет дополнительная информация, можно дальше подумать, почему вылетает. Пока остается руками развести.
Есть дополнительная информация. Ошибка возникает в строке
hr = CComObject<CTIOPortManager>::CreateInstance(&pTIOPortManager); — это мое приложение
RESULT WINAPI CComObject<Base>::CreateInstance(CComObject<Base>** pp) throw() — это АТЛ
это вызвается в нутри CreateInstance *** ATLTRY(p = new CComObject<Base>())
из него вызывается это *** void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
из new — это *** void * __cdecl _malloc_base (size_t size)
и последнее внутри _malloc_base *** res = _heap_alloc(size);
Просит 0х24 байта, но _heap_alloc не дает.
Вероятно какие-то проблемы с памятью или с настройками проекта. Как их найти и решить?
A>Вероятно какие-то проблемы с памятью или с настройками проекта. Как их найти и решить?
PS: проект создавался как обычная win32 dll без использования визардов для ActiveX объектов.
Здравствуйте, Alex1000000, Вы писали:
A>Просит 0х24 байта, но _heap_alloc не дает. A>Вероятно какие-то проблемы с памятью или с настройками проекта. Как их найти и решить?
Вероятно, но с такой ошибкой я никогда в своей практике не сталкивался. Может и есть для этого настройки проекта.
Вопрос решился успешно путем напсиания собственной реализации функций интерфейса IUnknown. Т.е. я просто скопировал в проект их стандартную реализацию из микрософтовских примеров.
Проблема была из-за того что я пытался честно, как учит учебник, унаследовать эти функции из стандартных ATL шаблонов, а они в реализации ATL слишком много хотят.
Спасибо Vi2 за поддержку.