ANSI-C中使用引用计数(译)

ANSI-C中使用引用计数(译)

原作者:Jean-David Gadina

原文地址:Reference counting in ANSI-C

关于:

内存管理在编写c程序时是一件困难的事情,

某些高等级的编程语言提供了不同的内存管理的方法。

主要有垃圾回收(garbage collection) 和引用计数(reference counting)。

本文将教给你如何在c语言中实现引用计数的内存管理系统。

从个人角度讲,本人(原文章作者)作为一名使用c语言和Objective-c语言的程序员,更加偏爱引用计数的方法。

因为这种方法隐含着对象所有权的概念。(It implies the notion of ownership on objects.)

Objective-C 的例子

在Objective-C中,当你通过 alloc 或者 copy 方法创建一个对象时,你拥有这个对象(you own the object)。这也就意味着将由你来负责释放(release)你的对象,保证该块内存被回收利用。

另外,对象也可以被保留(retained)。这种情况下他们也必须被释放(release)。

通过简便的方法获得对象,调用者并不拥有该对象,所以也没有必要去释放他们,释放的工作自然会由其他的类或者方法来做。

例如:

1 NSArray * object1 = [ NSArray array ];2 NSArray * object2 = [ [ NSArray alloc ] init ];3 NSArray * object3 = [ [ [ NSArrayarray ] retain ] retain ];

在这里,变量 object2 需要被release,,因为我们明确的通过 alloc 创建了它。

变量object3 则需要被release 两次,因为我们retain 了它两次。

如下:

1 [ object2 release ];2 [ [ object3 release ] release ];

C语言实现

作为一名c语言编程者,原文作者将要使用ANSI-C来实现objective-c 中的引用计数。

具体实施如下:

首先,我们需要为我们的内存纪录定义一个结构体,这个结构体看起来像是下面这个样子:

1 typedef struct2 {3 unsigned int retainCount4 void* data;5 }6 MemoryObject;

我们将 retain 计数 使用一个 无符号整形变量 rerainCount 来储存,遇到retain则增加改变量的值,遇到release 则减少改变量的值,当改变量的值为0的时候,就释放掉该对象的内存。

同时我们也需要自定义一个 分配函数(allocation function):

1 void * Alloc( size_t size )2 {3MemoryObject * o;4o = ( MemoryObject * )calloc( sizeof( MemoryObject ) + size, 1 );

我们最终是要返回内存对象的指针,所以我们需要进行一些计算:

第一、声明一个 指向char类型的指针,用来指向我们生成的内存对象结构体:

1 char * ptr = ( char * )o;

第二、通过给该指针增加内存对象结构体的大小来获取 用户自定义数据的内存地址:

2 ptr += sizeof( MemoryObject );

第三、将用户自定义数据内存地址传给 内存对象结构体中的 data指针,然后将引用计数变量的值设置为1:

3 o->data= ptr;4 o->retainCount = 1;

最后,返回ptr指针,这样使用者就不需要知道我们内存对象结构体的内部结构了。

5 return ptr;

下面是完整的函数:

1 void * Alloc( size_t size ) 2 { 3MemoryObject * o; 4char* ptr; 5o= ( MemoryObject * )calloc( sizeof( MemoryObject ) + size, 1 ); 6ptr= ( char * )o; 7ptr+= sizeof( MemoryObject ); 8o->retainCount = 1; 9o->data= ptr;10return ( void * )ptr;11 }

这样,我们成功的返回了用户指定的内存大小,隐藏了定义在用户数据前面的结构体。

要找回我们的数据(译者:应该是自定的结构体),只需要很简单的减去MemoryObject结构体 的大小即可:

拿Retain 函数举例:

1 void Retain( void * ptr )2 {3MemoryObject * o;4char* cptr;5cptr = ( char * )ptr;6cptr -= sizeof( MemoryObject );7o= ( MemoryObject * )cptr; 8o->retainCount++:9 }

在这里通过用户指针减去 MemoryObject 结构体的大小获得了,指向咱们之前自定义的结构体的地址,然后访问其中的 retainCount 变量,来增加引用计数。

Release 方法也是一样:

如此锐气,二十后生有之,六旬男子则更多见。

ANSI-C中使用引用计数(译)

相关文章:

你感兴趣的文章:

标签云: