1

私は安全にできると確信しています:

void funcA(VARIANT &V,_variant_t &vt)
{
    vt = V;
}

しかし、その逆はどうでしょうか。

void funcB(VARIANT &V,_variant_t &vt)
{
    V = vt;
}

COM 関連のスレッド化の問題が原因で、アプリで非常に奇妙な動作が見られます。しかし、バリアントを間違って使用してメモリを台無しにしていたのではないかと思いました。funcB では、VARIANT V は、COM 呼び出し用に準備されているセーフ配列の一部です。私の V=vt 行で、同じバリアントの割り当てが 2 回解除されると問題が発生する浅いコピーを行っていますか?

私は _variant_t が本当に好きで、すべての ::VariantXXX メソッドを避けています。コピーを自動化するために funcB で _variant_t を使用するきちんとした方法はありますか?

4

2 に答える 2

3

VARIANTにオブジェクトまたは が含まれているBSTR場合、safearray の割り当てを解除すると、所有していないリソースが解放されるため、safearray の割り当てを解除すると問題が発生しますしたがって_variant_t、セーフ配列またはセーフ配列のいずれかが破棄されると、もう一方は割り当て解除されたオブジェクトへの参照を持ちます。

たとえば、VARIANTに へのポインタが含まれている場合、 を複数回IUnknown呼び出すことで参照カウントが台無しになります。ReleaseAddRefBSTR

これが、メソッドVariantCopyを避けたい場合Variant*(私には理解できない理由で) を使用する必要がある理由です。_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(); 
}
于 2009-11-26T13:00:58.483 に答える
3

まず第一に、はい、代入演算子を使用してfuncB()浅いコピーのみを呼び出します (oaidl.h を調べてVARIANT定義を確認することをお勧めします。ユーザー定義の代入演算子がないため、浅いコピーが行われます)。コンパイラによって)。

これにより、浅いコピーにアクセスする前にコピー元の他のバリアントがクリアされた場合、未定義の動作が発生します (たとえば、バリアント型がVT_UNKNOWN指しているオブジェクトであった場合、 を呼び出して参照カウントを 0 に設定した後、単純に破棄できますIUnknown::Release())。

_variant_t別のオブジェクトにコピーするメソッドがないため、あまり役に立ちません-クラス定義についてはcomutil.hを参照してください-別のオブジェクトからそれ自体にコピーするだけです。

最も簡単な方法は、 を使用することVariantCopy()です。対処するときにセーフアレイが初期化されるかどうかはわかりません。各要素で初期化されている場合は、 をVT_EMPTY呼び出すだけVariantCopy()です。それ以外の場合は、最初に宛先を呼び出しVariantInit()て、宛先を初期化します。VariantCopy()初期化されていないランダムなデータを含む宛先を呼び出すと、未定義の動作が発生する可能性があります。

于 2009-11-25T06:43:22.297 に答える