对于被破坏对象的弱句柄,GCHandle.IsAllocated不返回false

时间:2012-05-09 15:30:39

标签: c++-cli

在某些C ++ / CLI代码中,我有一个本机类,它有一个工厂方法GetWrapper(),用于创建自己的托管.NET包装器对象。在内部,它通过GCHandle对其包装器进行弱引用。调用GetWrapper()时,将检查GCHandle并返回现有包装器的句柄,或者(如果它不再指向对象,因为旧的包装器对象已被垃圾收集器销毁)a新的一个被创建一个返回。

// .h
class NativeClass
{
public:
    WrapperClass^ GetWrapper();
private:
    WrapperClass^ GetNewWrapper();
    GCHandle m_wrapperGCHandle;
};

// .cpp
WrapperClass^ NativeClass::GetWrapper()
{
    if(m_wrapperGCHandle.IsAllocated)
    {
        try
        {
            WrapperClass^ wrapper = nullptr;
            wrapper = dynamic_cast<WrapperClass^>(wrapperGCHandle.Target);

            if(wrapper == nullptr)
            {
                return GetNewWrapper();
            }
            else
            {
                return wrapper;
            }
         }
         catch(System::InvalidOperationException^)
         {
             return GetNewWrapper();
         }
    else
    {
        return GetNewWrapper();
    }
}

WrapperClass^ NativeClass::GetNewWrapper()
{
    WrapperClass^ wrapper = gcnew WrapperClass(/*some args*/);
    m_wrapperGCHandle = GCHandle::Alloc(wrapper, GCHandleType::Weak);
}

现在奇怪的是m_wrapperGCHandle.IsAllocated 始终返回true,即使包装器已被垃圾收集。 MSDN tells to“在使用弱句柄时使用此属性来确定GCHandle是否仍然可用。”但它总是如此。如果它不可用,则目标是nullptr。

我错过了什么或者MSDN错了吗?

1 个答案:

答案 0 :(得分:2)

我对MSDN doco的读取是m_wrapprGCHandle.IsAllocated将返回true,直到调用m_wrapperGCHandle.Free - IsAllocated属性检查句柄的状态而不是引用的状态由把手握住。

如您所知,当对象被垃圾回收时,m_wrapperGCHandle.Target为空。我使用了与示例代码中的类似方法来生成托管包装类,并且我总是检查Target是否为null,并在Target为空时重新生成包装器对象。

另外,一个建议......它看起来好像你的代码中有句柄泄漏,因为你在没有相应GCHandle::Alloc调用的情况下调用m_wrapperGCHandle.Free。尝试在类构造函数中调用Alloc,并在析构函数中调用Free

NativeClass::NativeClass()
{
    m_wrapperGCHandle = GCHandle::Alloc(nullptr, GCHandleType::Weak);
}

NativeClass::~NativeClass()
{
    m_wrapperGCHandle.Free();
}

然后您的GetNewWrapper方法就是:

WrapperClass^ NativeClass::GetNewWrapper()
{
    m_wrapperGCHandle.Target = gcnew WrapperClass(/*some args*/);
}

您可以从if(m_wrapperGCHandle.IsAllocated) - else方法中删除GetWrapper链。