软件测试之之用户层垃圾回收算法[3]

发表于:2009-09-15来源:作者:点击数: 标签:软件测试用户算法垃圾
软件测试之之用户层垃圾回收算法[3] 软件测试方法 关键字: 数据库 设计 以上编码便是使用GCPtr类管理引用计数的一个初步实现,当然这里只是为了演示一下如何管理引用计数,并不是全部功能的实现。具体应用中还有许多操作符需要重载,将在后面进行介绍。 4.

软件测试之之用户层垃圾回收算法[3]   软件测试方法

关键字:数据库设计     以上编码便是使用GCPtr类管理引用计数的一个初步实现,当然这里只是为了演示一下如何管理引用计数,并不是全部功能的实现。具体应用中还有许多操作符需要重载,将在后面进行介绍。

    4. 构造函数和析构函数的说明

    可以看到在GCPtr的构造函数中,直接由内存地址定位到存放引用计数的位置,将引用计数加1。

    析构函数要做的事情也很简单,就是当一个GCPtr类型的变量释放时,直接由要释放的内存地址(已经存放到m_pAddr中)定位到存放引用计数的位置,将引用计数减1。

    这种方法在修改引用计数时效率非常高,与哈希表相比无需查表等操作。

    5. 需要修改引用计数的情况

    实际上,不仅仅是构造函数和析构函数要修改引用计数,牵涉指针的操作基本上都需要修改引用计数,主要有以下三种情况。
    1) 当将新地址赋给GCPtr时,需要将原来地址的引用计数减1,新的地址的引用计数加1,这时需要重载运算符“=”号。
    2) 当将一个GCPtr赋给另外一个GCPtr时,需要将等号左边的GCPtr指向的内存块的引用计数减1,等号右边的GCPtr指向的内存块的引用计数加1。
    3) 当需要对象的副本时,需要调用GCPtr的拷贝构造函数,如将对象当作参数传递给函数,作为函数的返回值等情况都会调用拷贝构造函数。由于复制的对象是指向相同的地址,而复制对象在释放时要调用析构函数,析构函数将引用计数减1,因此需要在拷贝函数里加1以维持引用计数的平衡。

    下面给出这几个操作的编码,由于构造函数和析构函数等在前面已经给出,所以这里省略。
    template <class T> class GCPtr {
    public:
            T *m_pAddr;    /* 用来记住定义的指针地址便于析构函数使用 */
    public:
            /* 拷贝构造函数 */
            GCPtr(const GCPtr &gcPtr)
            {
                   INT *p = (INT *)gcPtr.m_pAddr-1;
                   *p += 1;
                   m_pAddr = gcPtr.m_pAddr;
            }
            T *operator=(T *t)
            {
                   /* 将原来指向的内存引用计数减1 */
                   INT *p = (INT *)m_pAddr-1;
                   *p-= 1;
                   m_pAddr = t;
                   /* 将新指向的内存的引用计数加1 */
                   p = (INT *)t-1;
                   *p += 1;
                   return t;
            };
            GCPtr & operator = (GCPtr &r)
            {
                   /* 将原来指向的内存引用计数减1 */
                   INT *p = (INT *)m_pAddr-1;
                   *p-= 1;
                   m_pAddr = r.m_pAddr;
                   /* 将新指向的内存的引用计数加1 */
                   p = (INT *)r.m_pAddr-1;
                   *p += 1;
                   return r;
            }; 
    };

    6. 垃圾收集功能的实现

    引用计数的功能实现后,接着要做的就是实现垃圾内存回收,也就是将引用计数为0的内存全部释放后,如何去访问已经分配的内存?必须用一张表来保存所有已分配的内存地址,可以在GC_Malloc()函数分配内存时就将分配的内存地址保存到哈希表里,然后就可以通过对哈希表的遍历来实现对内存垃圾的回收,由于牵涉哈希表的操作,除了修改GC_Malloc()函数外,还需要增加一个初始化函数,在初始化函数里创建哈希表,以下便是实现编码。

原文转自:http://www.ltesting.net