Возникает access violation при drag'n'drop из одного экземпляра моего приложения в другой. Исключение бросается после вызова pUnkForRelease->Release(), не могу понять в чем дело.
Делаю так:
В IDataObject::GetData
class TDataObject : public IDataObject;
HRESULT TDataObject::GetData(FORMATETC* pFormatetc, STGMEDIUM* pmedium)
{
// ...
pmedium->tymed = TYMED_HGLOBAL;
pmedium->hGlobal = ::GlobalAlloc(GHND, nSize);
pmedium->pUnkForRelease = new TUnknownForRelease(pmedium->hGlobal);
// ...
}
Здравствуйте, Tom, Вы писали:
I>> pmedium->tymed = TYMED_HGLOBAL; I>> pmedium->hGlobal = ::GlobalAlloc(GHND, nSize); I>> pmedium->pUnkForRelease = new TUnknownForRelease(pmedium->hGlobal); Tom>pmedium->pUnkForRelease->AddRef(); // Копируем "на верх", а значит должны увеличить кол-во ссылок I>> // ...
Вряд ли, со счетчиком все в порядке.
Скорее всего, GHND не держит в память само значение hGlobal, поэтому вполне могло переместиться в силу других причин. Т.о. налицо рассогласование pmedium->hGlobal и TUnknownForRelease::hGlobal.
I>> pmedium->pUnkForRelease = new TUnknownForRelease(pmedium->hGlobal);
Tom>pmedium->pUnkForRelease->AddRef();// Копируем "на верх", а значит должны увеличить кол-во ссылок
I>> // ...
I>>}
I>>
Дело в том, что в конструкторе TUknownForRelease я сразу присваиваю nRefs = 1, так что не думаю что в этом дело.
Re[3]: Вопрос по Drag'n'Drop STGMEDIUM->pUnkForRelease
Здравствуйте, Vi2, Вы писали:
Vi2>Скорее всего, GHND не держит в память само значение hGlobal, поэтому вполне могло переместиться в силу других причин. Т.о. налицо рассогласование pmedium->hGlobal и TUnknownForRelease::hGlobal.
Позволю себе с Вами не согласиться. Пусть себе память переместилась, но хендл на память, который выделила GlobalAlloc(GMEM_MOVEABLE, ...) должен был остаться прежним. Тем более, что выделение и освобождение памяти происходит в одном процессе — метод IDataObject::GetData вызывается в принимающем приложении и ReleaseStgMedium там же.
Кроме того, мне кажется, исключение вылетает именно в случае если присутствует строка "delete this" в TUnknownForRelease::Release(). Без нее с hGlobal никаких проблем не появляется.
Re[4]: Вопрос по Drag'n'Drop STGMEDIUM->pUnkForRelease
Более того, если этот хендл мог бы меняться, как Вы говорите, я тогда не представляю себе как должен работать механизм pUnkForRelease Что он сможет сделать, если все изменилось и исходные хендлы потеряны на момент его активации?
Re[5]: Вопрос по Drag'n'Drop STGMEDIUM->pUnkForRelease
Здравствуйте, Ignoramus, Вы писали:
I>Позволю себе с Вами не согласиться. Пусть себе память переместилась, но хендл на память, который выделила GlobalAlloc(GMEM_MOVEABLE, ...) должен был остаться прежним. Тем более, что выделение и освобождение памяти происходит в одном процессе — метод IDataObject::GetData вызывается в принимающем приложении и ReleaseStgMedium там же.
I>Кроме того, мне кажется, исключение вылетает именно в случае если присутствует строка "delete this" в TUnknownForRelease::Release(). Без нее с hGlobal никаких проблем не появляется.
I>Более того, если этот хендл мог бы меняться, как Вы говорите, я тогда не представляю себе как должен работать механизм pUnkForRelease Что он сможет сделать, если все изменилось и исходные хендлы потеряны на момент его активации?
Согласен. Но из кода, который был приведен, другое предположение и не последовало бы — там более-менее все в порядке. Единственное: nRefs обычно защищают при многопоточности и т.п. Раннее освобождение объекта было бы легко установить.
Через "delete this" в Release удаляется каждый (по крайней мере в ATL) СОМ объект, и никто не жалуется на вылет приложений из-за этого. Чаще "вылетают" при этом операторе, когда библиотека поддержки (по очистке ли ресурсов, при обращении к СОМу etc.) выгрузилась.