gnustep objective-c 引用计数浅析

这篇博客介绍了作者对gnustep中Objective-C引用计数的初步研究,通过在Windows环境下运行实验代码,观察并分析了对象内存布局,特别是对象头部的4个字节与retainCount的关系。文章指出,对象的retainCount等于头部索引值加1,但并未深入探讨gnustep与Apple实现的区别,强调gnustep在Windows下的框架仅是对Cocoa的模仿,对于理解Apple平台的实际内存管理原理有限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

只是浅浅的看了一下,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平台的实现原理。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值