美文网首页bentley开发C++\CLI
C++/CLI中的确定性垃圾回收与mdl.net中Element

C++/CLI中的确定性垃圾回收与mdl.net中Element

作者: 左图右码 | 来源:发表于2022-04-09 14:24 被阅读0次

C++/CLI中的确定性垃圾回收

托管语言中自动垃圾回收导致回收的时机是不确定的,只有托管C++实现了确定性的回收机制,在一本名著中这么写到(我翻译过来的):

析构器和终结器的IL实现
在我们对垃圾收集的介绍中,您看到了GC如何在清理对象之前自动调用终结器。很明显。NET直接支持终结器。但没有提到析构器。这是因为NET 框架的自动垃圾收集内存模型不利于确定性析构器的概念。在这种背景下,C++/CLI使用Dispose模式来实现析构器和终结器语义。
C++/CLI Dispose模式使用以下规则:
■如果一个class有终结器(!typename)或析构器(~typename),编译器为该类生成Dispose(bool)方法。编译器生成的代码检查bool,如果传递了true值,它会调用析构器(~typename),如果传递了false值,它会调用终结器(!typename)。
■对于任何定义析构器(~typename)的对象,编译器自动实现该对象的System::IDisposable接口,并生成满足该接口的Dispose()方法。此编译器生成的Dispose方法调用Dispose(true),以便执行析构器(~typename)。然后,它调用GC::SuppressFinalize(this),它将该对象从Finalization队列中删除,因为该对象现在其析构器已被调用,因此无需再使用终结器。
■对于任何定义终结器的对象(!Typename),编译器自动生成一个Finalize方法,该方法包含了System::Object::Finalize()。此编译器生成的Finalize方法调用Dispose(false),以便终结器(!Typename)被执行。

namespace test
{
    public ref class A
    {
    public:
        A() {}
    private:
        !A() {}
    };
    public ref class B
    {
    public:
        B() {}
    private:
        ~B() {}
    };
    public ref class C
    {
    public:
        C() {}
    private:
        !C() {}
        ~C() {}
    };
}

以上代码编译后的IL反编译如下,可以看到编译器塞入了哪些内容,符合上述的解释:

QQ20220409-142325.png

请注意,析构器和终结器都可以放入私有部分,因为delete和GC不是直接访问他们,这和标准C++不同。
另外,如果想要手工执行回收,不需要调用终结器,则GC::SuppressFinalize(Object^)设置就能删除终结器的自动调用。而System::GC::ReRegisterForFinalize(Object^)则会将object的句柄重新加入Finalization终结器列表,就又可以自动回收了。
比如,在mdl.net中最常用的Element中AdjustFinalizeRequirement用于调整是否需要调用终结器(反编译代码):

internal unsafe void AdjustFinalizeRequirement()
{
    int num;
    GC.SuppressFinalize(this);
    ref byte modopt(IsExplicitlyDereferenced) pinned numRef = (ref byte modopt(IsExplicitlyDereferenced)) &(this.ElementHandle[0]);
    EditElementHandle* handlePtr = numRef;
    if ((0L == Bentley.DgnPlatform.ElementHandle.PeekElementDescrCP((ElementHandle modopt(IsConst)* modopt(IsConst) modopt(IsConst)) handlePtr)) && 
(0L == Bentley.DgnPlatform.EditElementHandle.GetIElementState(handlePtr)))
    {
        num = 0;
    }
    else
    {
        num = 1;
    }
    if (((byte) num) != 0)
    {
        GC.ReRegisterForFinalize(this);
    }
}

如果ElementHandle中没有元素描述符和IElementState也为空的话,就没必要调用终结器。

相关文章

  • C++/CLI中的确定性垃圾回收与mdl.net中Element

    C++/CLI中的确定性垃圾回收 托管语言中自动垃圾回收导致回收的时机是不确定的,只有托管C++实现了确定性的回收...

  • JVM的垃圾回收机制

    一、垃圾回收 GC(Garbage Collection):JAVA/.NET中的垃圾回收器。Java是由C++发...

  • Java内存泄漏

    本文将会介绍: C++中的内存泄露 Java内存管理与垃圾回收 Java中的内存泄漏 一、C++中的内存泄露 在大...

  • finalize

    finalize 它是Object中的一个方法,与C++中的析构函数类似,与垃圾回收有关,在java 9中已弃用。...

  • java内存结构和GC机制

    Java垃圾回收概况 Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C...

  • 垃圾回收

    背景 与C++对比,C++的内存回收是有C++的代码控制的,而JAVA的内存回收是由JVM的垃圾回收器控制的,看起...

  • Java 内存区域和GC机制一篇就够了

    Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之...

  • 垃圾回收

    垃圾回收一共分两种:栈中的垃圾回收和堆中的垃圾回收 栈中的垃圾回收 JS 引擎有一个记录当前执行状态的指针,称为 ...

  • Thinking In Java 阅读笔记(四)

    垃圾回收 与C++一样,Java也需要进行垃圾回收,但是它们之间是有不同之处的。C++允许你为一个类定义一个撤消函...

  • JVM——垃圾回收与算法

    前言 今天就来介绍一下垃圾回收与算法。 垃圾回收与算法 如何确定垃圾 引用计数法 在 Java 中,引用和对象是有...

网友评论

    本文标题:C++/CLI中的确定性垃圾回收与mdl.net中Element

    本文链接:https://www.haomeiwen.com/subject/rdepsrtx.html