I have a function
BOOL AltairListDialog::GetDocuments()
{
CComQIPtr<AXAPILib::ICollection> m_Collection;
HRESULT hr = m_Collection.CoCreateInstance(L"Axapi.Collection");
AXAPILib::ICollection *indices = (AXAPILib::ICollection*) m_Collection.p;
int status;
COleVariant ind;
ind.vt = VT_DISPATCH;
ind.pdispVal = (IDispatch*) indices;
return TRUE;
}
I use a DLL which implements AXAPILib::ICollection. The function returns “Access violation” after “return TRUE;” but I don’t know why. Any suggestions?
Well, fishing for suggestions does not really fit Stack Overflow’s question and answer format, so it would not be unright to vote to close the question. On the other hand, many others may be doing the same Bad Things™, and could benefit from being told about it. So:
Don’t use C style casts like
(AXAPILib::ICollection*) m_Collection.p. If it does not compile without the cast, then it is simply wrong. Adding the cast then hides a bug.In this case particular case removing the cast should not have any effect. But it is wholly ungood to have such casts in the code. They not only hide bugs (by suppressing warnings and errors), they actively introduce bugs.
Don’t use C style casts like
(IDispatch*) indices. If the code does not compile wihout the cast, then it is simply wrong. Adding the cast then hides a bug.For this second cast, removing the cast may have a drastic effect, or not. The potential drastic effect is that the code no longer compiles. In that case, you know what’s wrong (although most likely there’s nothing wrong here except the cast itself).
Don’t mix smart pointers and “raw” pointers unless you really, Really REALLY know what you’re doing.
Here the smart pointer’s destructor automatically
Release()es the object on return from the function. The object is newly created and has no other references to it. Hence its reference count goes to zero now, and it is destroyed.After the function return, referring to the destroyed object is Undefined Behavior and very likely to produce the undesired behavior that you have observed.
One CURE FOR THAT is to ask the smart pointer to give away its ownership of the contained raw pointer.
For the particular Microsoft smart pointer that you’re using its MSDN Library documentation says that you can do that by calling the
Detach()member function. Confusingly, wrt. naming, for the C++ standard library’s smart pointers, and as a general convention, it’s done by calling arelease()member. It’s worth noting that MicrosoftRelease()and standard libraryrelease()are two very different operations, respectively ref count decrement versus, uh, detach…Finally, it is a good idea to not use the Windows API’s
BOOL, and instead use C++bool. One reason is just to avoid eye-searing all uppercase in the code. And a more technical reason is thatboolhas just two valid values, namelyfalseandtrue, whileBOOLhas a zillion different valid values, which, when a novice programmer writes things likeexpression() == TRUE, likely leads to bugs.