I'm fairly certain that I can safely do:
void funcA(VARIANT &V,_variant_t &vt)
{
vt = V;
}
But what about the other way around:
void funcB(VARIANT &V,_variant_t &vt)
{
V = vt;
}
I've been seeing some REALLY weird behaviour in my app which I pu开发者_Python百科t down to COM-related threading issues. But then I got wondering if I was screwing up memory using variants wrongly. In funcB, the VARIANT V is part of a safe-array being prepared for a COM call. With my V=vt line, am I doing a shallow copy which will break things when the same variant gets deallocated twice?
I really like _variant_t and avoiding all the ::VariantXXX methods, is there a neat way to use _variant_t in funcB to automate the copying?
First of all, yes, by using the assignment operator the way you do in funcB()
you invoke shallow copying only (you might want to look into oaidl.h to see the VARIANT
definition - it has no user-defined assignment operator and therefore shallow copying is done by the compiler).
This gets you into undefined behaviour if the other variant you copied from is cleared before you access the shallow copy (for example, if the variant type was VT_UNKNOWN
the object pointed to could simply be destroyed after setting the reference count to 0 by calling the IUnknown::Release()
).
_variant_t
will not help you much since it has no methods for copying to another object - see comutil.h for class definition - it only copies from another object to itself.
The easiest way would be to use VariantCopy()
. Not sure if the safearray will be initialized when you deal with it. If it is initialized with each element having VT_EMPTY
you can just call VariantCopy()
. Otherwise first call VariantInit()
on the destination to initialize the destination. Calling VariantCopy()
for a destination containing random uninitialized data can lead to undefined behaviour.
If the VARIANT
contains an object or a BSTR
you will run into trouble when you deallocate the safearray since safearray deallocation will free the resource which it doesn't own. So when either the _variant_t
or the safearray is destroyed the other will have a reference to a deallocated object.
For example if the VARIANT
contains a pointer to IUnknown
you'll mess up the reference count by calling Release
more times than AddRef
, if it contains a BSTR
you'll just copy the pointer and not allocate a new string for the new variable.
This is why you should use VariantCopy
, if you want to avoid Variant*
methods (for a reason I can't understand) this can be done with _variant_t::Detach()
void funcB(VARIANT &V,_variant_t &vt)
{
_variant_t temp = vt;
V = temp.Detach();
// or in one line V = _variant_t(vt).Detach();
}
精彩评论