Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ cli GCHandle.IsAllocated不会为已销毁对象的弱句柄返回false_C++ Cli - Fatal编程技术网

C++ cli GCHandle.IsAllocated不会为已销毁对象的弱句柄返回false

C++ cli GCHandle.IsAllocated不会为已销毁对象的弱句柄返回false,c++-cli,C++ Cli,在一些C++/CLI代码中,我有一个本机类,它有一个工厂方法GetWrapper(),用于创建自己的托管.NET包装对象。在内部,它通过GCHandle持有对其包装器的弱引用。调用GetWrapper()时,将检查GCHandle并返回现有包装的句柄,或者(如果它不再指向对象,因为旧包装对象已被垃圾收集器销毁)创建一个新的包装并返回 // .h class NativeClass { public: WrapperClass^ GetWrapper(); private: Wra

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

// .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);
}
/.h
类本地类
{
公众:
包装器类^GetWrapper();
私人:
WrapperClass ^GetNewWrapper();
GCHandle m_包装器GCHandle;
};
//.cpp
包装器类^NativeClass::GetWrapper()
{
if(m_wrapperGCHandle.IsAllocated)
{
尝试
{
WrapperClass^ wrapper=nullptr;
wrapper=dynamic_cast(wrapperGCHandle.Target);
if(wrapper==nullptr)
{
返回GetNewWrapper();
}
其他的
{
返回包装器;
}
}
捕获(系统::InvalidOperationException^)
{
返回GetNewWrapper();
}
其他的
{
返回GetNewWrapper();
}
}
WrapperClass^NativeClass::GetNewWrapper()
{
WrapperClass^wrapper=gcnew WrapperClass(/*一些参数*/);
m_wrapperGCHandle=GCHandle::Alloc(wrapper,GCHandleType::弱);
}
现在奇怪的是,
m_wrapperGCHandle.IsAllocated
始终返回true,即使包装已被垃圾收集。MSDN允许“在使用弱句柄时使用此属性来确定GCHandle是否仍然可用。”。但这总是正确的。如果不可用,则目标为空PTR


我是否遗漏了什么或MSDN有错?

我对MSDN文档的理解是
m_wrapprgHandle.IsAllocated
将返回true,直到调用
m_wrappergHandle.Free
-IsAllocated属性检查句柄的状态,而不是句柄所持有的引用的状态

正如您所注意到的,
m_wrapperGCHandle.Target
在垃圾收集对象时为null。我使用了与示例代码中类似的方法来生成托管包装类,我总是检查
Target
是否为null,如果
Target
为null,则重新生成包装对象

另外,还有一个建议……在我看来,您的代码中似乎存在句柄泄漏,因为您在调用
GCHandle::Alloc
时没有相应的
m包装器GCHandle.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*/);
}

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

代码中存在隐式线程竞争。GC可能在您测试IsAllocated后立即运行。@HansPassant是的,它当前不是线程安全的