天天看点

gnustep objective-c 引用计数浅析

只是浅浅的看了一下,gnustep是有源代码的,可以到官网下载看看。

是学习了ios与os x多线程和内存管理一书的实验代码。

#import <Foundation/Foundation.h>

@interface ClassA: NSObject
{
    int k;
}
-(void) print;
@end

@implementation ClassA
-(id) initWithK: (NSNumber *) number
{
    if (self = [super init])
    {
        k = [number intValue];
    }
    return self;
}

-(void) print
{
    NSLog(@"k=0x%08x", k);
}
@end

void print_buf(char *buf, int length, int mode)
{
    int i;
    printf("buf addr=%p length=%d\n", buf, length);
    for (i = 0; i < length; ++i)
    {
        if (mode == 0)
        {
            printf("%02x", (unsigned char)buf[i]);
        }
        else
        {
            printf("%02c", (unsigned char)buf[i]);
        }
        if ((i + 1) % 8 == 0)
        {
            printf(" ");
        }
    }
    printf("\n");
}

int main(const int arg, const char *argv[])
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    
    char *b;
    ClassA *ca = [[ClassA alloc]initWithK: [NSNumber numberWithInt: 0xDEADBEEF]];
    b = (char *)ca;
    NSLog(@"ca addr=%p", ca);
    [ca print];
    NSLog(@"retainCount=%i", [ca retainCount]);
    print_buf(b - 8, 16, 0);
    [ca retain];
    print_buf(b - 8, 16, 0);
    [ca retain];
    print_buf(b - 8, 16, 0);
    NSLog(@"retainCount=%i", [ca retainCount]);
    [ca release];
    print_buf(b - 8, 16, 0);
    [ca release];
    print_buf(b - 8, 16, 0);
    NSLog(@"retainCount=%i", [ca retainCount]);

    printf("1 value=0x%08x\n", b, *(int *)b);
    printf("2 value=0x%08x\n", *((int *)*(int *)b));
    printf("3 value=0x%08x\n", *((int *)*((int *)*(int *)b)));
    print_buf((char *)(*((int *)*(int *)b)), 8, 1);

    [ca release];

	[pool drain];
	return 0;
}
           

在windows下的输出

2015-02-10 09:22:05.626 cpro[992] ca addr=0x29b1078

2015-02-10 09:22:05.629 cpro[992] k=0xdeadbeef

2015-02-10 09:22:05.633 cpro[992] retainCount=1  这里输出retainCount是1

buf addr=029B1070 length=16

0000000000000000 c0304000efbeadde  注意索引位置4-7的地方是0 k值在对象开始地址偏移4个字节的位置

那么对象开始地址的4个字节的意义是什么,估计应该和oop有关的,虚表继承之类的

buf addr=029B1070 length=16

0000000001000000 c0304000efbeadde

buf addr=029B1070 length=16

0000000002000000 c0304000efbeadde  注意索引位置4-7的地方是2

2015-02-10 09:22:05.637 cpro[992] retainCount=3 这里输出retainCount是3

buf addr=029B1070 length=16

0000000001000000 c0304000efbeadde  注意索引位置4-7的地方是1

buf addr=029B1070 length=16

0000000000000000 c0304000efbeadde

2015-02-10 09:22:05.641 cpro[992] retainCount=1 这里输出retainCount是3

1 value=0x029b1078

2 value=0x00403040

3 value=0x670170c0

4 value=0x670170c0

buf addr=00403040 length=8

0?p00g0?p00g

基本上就是retainCount=索引位置4-7的地方的值+1,在分配对象前面加4个字节的头部用来存储索引计数。对于实例变量k值(这里是0xdeadbeef)前面的四个字节的意义,可以用静态反汇编工具或windows下的debug工具看一下,可能还不如看源码来的快。注意:这里没有深究的原因是,gnustep和apple的实现是完全不同的,gnustep在windows下的框架只是模仿cocoa的,内部可能完全不同。所以,对于理解apple平台只是有点帮助,并不是apple平台的实现原理。