Создание объекта через CComObject
От: Alex1000000  
Дата: 02.06.09 11:09
Оценка:
Первый раз в жизни нужно сделать класс как СОМ объект. Интерфейсы для объекта находятся в 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 — все пока заглушки
.

DECLARE_NO_REGISTRY()
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(MyPortManager)
COM_INTERFACE_ENTRY(IRTCPortManager3)
END_COM_MAP()
};
Re: Создание объекта через CComObject
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.06.09 11:53
Оценка:
Здравствуйте, Alex1000000, Вы писали:

A>Проблема заключается в том, что при попытке создания моего класса и по CComObject и по new вылетает "access violation" — попытка доступа по адресу 0.


Вот и покажи код создания твоего класса.

A>Вероятно класс должен содержать какие-то поля данных. Вопрос — какие? Я объявляю класс так как в имеющихся примерах, и никакие данные в примерах не объявляются.


В классе, тобой объявленным, достаточно данных, чтобы быть СОМ объектом.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Создание объекта через CComObject
От: Alex1000000  
Дата: 02.06.09 12:48
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Вот и покажи код создания твоего класса.


Какой код?

В моем коде сейчас все функции — заглушки, конструктор — пустой. Реальный код создания класса сидит где-то в ATL. И этот код, вероятно, ищет переменную типа RefCounter или какой-то указатель, какие-то данные, которые должны быть объявлены в СОМ объекте по умолчению, но я о них не знаю, поэтому они и не объявлены. Может нужно включить еще кого-то в родители?

В программе класс создается вот так:

CComObject<MyPortManager> *pMyPortManager = NULL;
hr = CComObject<MyPortManager>::CreateInstance(&pMyPortManager);

или так:

pMyPortManager = new CComObject<MyPortManager>;

Падают оба одинаково.
Re[3]: Создание объекта через CComObject
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.06.09 13:05
Оценка:
Здравствуйте, Alex1000000, Вы писали:

A>В программе класс создается вот так:

A>CComObject<MyPortManager> *pMyPortManager        = NULL;
A>hr = CComObject<MyPortManager>::CreateInstance(&pMyPortManager);

Вот здесь hr == S_OK? Код ведь правильный. Но потом при использовании pMyPortManager нужно учитывать, что объект создается с нулевым счетчиком ссылок.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Создание объекта через CComObject
От: Alex1000000  
Дата: 02.06.09 14:16
Оценка:
"access violation" вылетает именно из этой строки: hr = CComObject<MyPortManager>::CreateInstance(&pMyPortManager);
Из нее программа уже не выходит как нужно, а попадает сразу в ловушку __except. Возможности отладки у меня ограничены текстовым логом и по логу я вижу, что вызывается мой конструктор (пустой) и затем сразу сообщение из __except.
Re[5]: Создание объекта через CComObject
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.06.09 04:30
Оценка:
Здравствуйте, 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
Если будет дополнительная информация, можно дальше подумать, почему вылетает. Пока остается руками развести.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Создание объекта через CComObject
От: Alex1000000  
Дата: 05.06.09 12:54
Оценка:
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 не дает.

Вероятно какие-то проблемы с памятью или с настройками проекта. Как их найти и решить?
Re[7]: Создание объекта через CComObject
От: Alex1000000  
Дата: 05.06.09 13:19
Оценка:
A>Вероятно какие-то проблемы с памятью или с настройками проекта. Как их найти и решить?
PS: проект создавался как обычная win32 dll без использования визардов для ActiveX объектов.
Re[7]: Создание объекта через CComObject
От: Vi2 Удмуртия http://www.adem.ru
Дата: 08.06.09 04:43
Оценка:
Здравствуйте, Alex1000000, Вы писали:

A>Просит 0х24 байта, но _heap_alloc не дает.

A>Вероятно какие-то проблемы с памятью или с настройками проекта. Как их найти и решить?

Вероятно, но с такой ошибкой я никогда в своей практике не сталкивался. Может и есть для этого настройки проекта.

Есть форумы Средства разработки или WIN API, в которых могут подсказать.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re: Создание объекта через CComObject
От: Alex1000000  
Дата: 15.06.09 12:22
Оценка:
Вопрос решился успешно путем напсиания собственной реализации функций интерфейса IUnknown. Т.е. я просто скопировал в проект их стандартную реализацию из микрософтовских примеров.
Проблема была из-за того что я пытался честно, как учит учебник, унаследовать эти функции из стандартных ATL шаблонов, а они в реализации ATL слишком много хотят.
Спасибо Vi2 за поддержку.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.