2009-04-05 3 views
0

Моя программа разбивается каждый раз, когда я пытаюсь сохранить COM-указатель в структуре, а затем попытаюсь использовать исходный указатель. У меня нет отладочного доступа, чтобы точно сказать, что случилось.Сохранение COM-указателя в структуре

pRend->cp = cpRT; 

ID2D1SolidColorBrush *scBrush; 
ERF(cpRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::CornflowerBlue), &scBrush)); 

Он падает на CreateSolidColorBrush. Однако, если я прокомментирую pRend-> cp = cpRT, это не так. Кстати, pRend-> cp и cpRT имеют тип ID2D1HwndRenderTarget *.

ответ

0

Как оказалось, мне удалось остановить сбой, выделив pRend с помощью malloc. Это не проблема, потому что я позвоню бесплатно, когда мне это больше не понадобится. Меня интересует, почему вызов malloc исправляет это. Я привык делать Datatype * var;, а затем просто используя var. Это плохо?

+0

Да. var не указывает нигде, пока вы не назначите ему цель, будь то куча (из malloc) или другая переменная (var = & data_var). Если вы просто используете его немедленно, он перезапишет некоторый случайный бит памяти в зависимости от того, что осталось в нем, и может потерпеть крах (или сбой более тонко). – puetzk

+0

Wow я не знал, что O_O – scrutr

+0

Не используйте malloc. Используйте новое в своей структуре. Таким образом, когда вы вызываете delete (не бесплатно), будет вызван деструктор умного указателя. – jmucchiello

0

Непонятно, сколько кода существует между тем, когда вы назначаете его в структуру, а затем используете его в CreateSolidColorBrush. Если это нетривиальное количество времени, возможно, у вас есть проблема с подсчетом ссылок.

Вы храните необработанный указатель в структуре? Если это так, переключите его на CComPtr и посмотрите, не исчез ли крушение.

Например. Если у вас было следующее определение типа для значения pRend (назовите его Render), и значение pRend было уничтожено до создания вызова CreateSolidColorBrush, вы могли бы увидеть это поведение.

struct Render { 
    ID2D1HwndRenderTarget *pCt; 
    ~Render() { 
    pCt->Release(); 
    } 
}; 
0

Это умный указатель. Я угадывая, вы невольно вызываете выпуск на нем. В частности, оператор address (unary op &) переопределяется для вызова Release().

Посмотрите, что произойдет, если вы присвоите ему ссылку, ID2D1HwndRenderTarget * &.

Очевидно, что если вы присвоите ссылку, вы не сможете ее переустановить.

+0

Это не умный указатель. – scrutr

1

Вместо назначения непосредственно QI, а затем хранить т.е.

pRend->cp = cpRT; 

следует заменить

cpRT->QueryInterface(&pRend->cp); 
+0

Вам не нужно передавать IID в QueryInterface()? Кроме того, в чем смысл вызова QueryInterface() в этой ситуации? Это значит, что он увеличивает счетчик ссылок интерфейса? Если у вас уже есть правильный указатель интерфейса, почему бы не вызвать AddRef() вместо этого? – bk1e

+0

В терминологии COM вы не должны назначать что-либо напрямую. Это должно быть сделано с использованием QI. Если вы используете интеллектуальные указатели (CComQIPtr), вы можете назначить напрямую. – Vinay

+0

Если у вас уже есть указатель на интерфейс, тогда да - вы, вероятно, должны снова вызвать AddRef(), а не QI(). –

Смежные вопросы