views:

163

answers:

4

My program is crashing every time I try to store a COM pointer into a struct, and then later try to use the original pointer. I don't have debug access to tell exactly what's wrong.

pRend->cp = cpRT;

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

It crashes on CreateSolidColorBrush. However, if I comment out pRend->cp = cpRT, it doesn't. By the way, pRend->cp and cpRT are of type ID2D1HwndRenderTarget *.

A: 

It's unclear how much code exists between when you assign it into the struct and later use it in CreateSolidColorBrush. If it's a non-trivial amount of time, it's possible that you have a reference counting issue.

Are you storing a raw pointer in the struct? If so, switch it to a CComPtr and see if the crash goes away.

For instance. If you had the following type definition for the value of pRend (call it Render) and the value pRend was destroyed before making the CreateSolidColorBrush call, you could see this behavior.

struct Render { 
  ID2D1HwndRenderTarget *pCt;
  ~Render() {
    pCt->Release();
  }
};
JaredPar
A: 

As it turns out, I managed to stop the crashing by allocating pRend with malloc. This is not a problem because I will call free when I don't need it anymore. I'm interested in why calling malloc fixes this though. I'm used to just doing Datatype * var; and then just using var. Is that bad?

scrutr
puetzk
Wow I did not know that O_O
scrutr
Don't use malloc. Use new on your struct. This way when you call delete (not free) the smart pointer's destructor will be called.
jmucchiello
It's not a smart pointer.
scrutr
A: 

It's a smart pointer. I'm guessing you're inadvertantly calling release on it. In particular, it's addressof operator (unary op&) is overriden to call Release().

See what happens if you instead assign it to a reference, an ID2D1HwndRenderTarget*&.

Obviously, if you assign to a reference, you won't be able to reseat it.

tpdi
It's not a smart pointer.
scrutr
+1  A: 

Instead of assigning directly QI and then store i.e.,

pRend->cp = cpRT;

should be replaced with

cpRT->QueryInterface(&pRend->cp);
Vinay
Don't you need to pass an IID to QueryInterface()? Also, what is the benefit of calling QueryInterface() in this situation? Is it that it increments the interface's reference count? If you already have the right interface pointer, why not call AddRef() instead?
bk1e
In COM terminology, you should not assign anything directly. It should be done using QI. If you are using smart pointers(CComQIPtr) then you can assign directly.
Vinay
If you already have the right interface pointer, then yes -- you probably should call AddRef() rather than QI() again.
Euro Micelli