软件测试之用户层垃圾回收算法[2] 软件测试方法
关键字:数据库设计可不可以在GCPtr类里面直接定义一个变量来保存引用计数呢?答案是否定的。因为指针和内存并不是一一对应的关系,而是可能有多个指针指向同一块内存。引用计数必须和分配的内存一一对应,如果GCPtr类里面直接定义一个变量来保存引用计数的话,当另外一个GCPtr对象指向一个已有GCPtr对象指向的内存时,如何去增加引用计数?这显然是无法实现的,所以必须设计一个和分配内存一一对应的保存引用计数的地方。
首先想到的就是设计一张表来保存分配的内存地址及对应的引用计数,重点是考虑在操作引用计数时,如何快速通过分配的内存地址定位到对应的引用计数变量。
这时也许有人会想到用一个哈希表之类的能够快速查找的数据结构来保存内存地址和引用计数,还有没有更快的方法呢?
更快的方法就是通过内存地址直接就可以访问引用计数,这就要求引用计数保存在和分配的内存连续的空间上。但问题又来了,系统提供的内存管理算法并没有留下可以保留引用计数的位置,要实现这样的功能就必须写一个自己的内存管理算法。
由于是在应用程序层,写一个内存管理算法实际上还是需要先向操作系统申请一大块内存,然后使用自己的内存管理算法来管理这块内存,问题是如何知道需要向操作系统申请多少内存呢?也许目前需要1兆内存,但下个版本也许又需要2兆内存,总之内存的需求是变化无常的,使用自己的内存管理算法在实际应用中必然存在浪费的情况,所以这种方法实现起来不能令人满意。
难道又退回到用哈希表吗?用哈希表在每次指针赋值时,增加引用计数需要进行哈希表的查找,对一个赋值语句来说,开销实在太大了,自己写内存管理算法也行不通,所以还是想想有没有别的方法吧。那么,可不可以继承系统的内存管理算法呢?
由于系统的内存管理没有在管理上给分配的内存预留引用计数位置,但可以在分配给用户使用的内存上自己预留引用计数的空间。比如在32位系统上,要想分配一个128 B的内存块,那就应该分配一个132 B的内存块,将内存块前面4个字节留作引用计数,将第4个字节后的空间返回给程序使用。这样当需要通过内存地址来操作引用计数时,直接就可以将指针地址向后移4个字节,然后在这4个字节上写引用计数就可以了,这样就可以设计一个用户的内存管理函数如下。
#define INT_LEN 4
void *GC_Malloc(size_t size)
{
void *p = malloc( size + INT_LEN );
if ( p != NULL )
{
return (void *)((char *)p+INT_LEN);
}
return NULL;
}
当然还要设计一个对应的释放函数如下。
void GC_Free(void *p)
{
void *pFree = (void *)((char *)p – INT_LEN);
free(pFree);
}