cocoa core foundation内存管理

core foundation也是支持ARC的,也有count的概念, 当一个实体的count(引用次数)为0的时候,系统就会回收这个实体的资源.

1.通过函数有关键字"create"和"copy"的函数创建的对象的count都是1, 同时真正的拥有这个对象,对象具体的生命周期要看变量什么时候使用CFRelease函数,如果在一个作用域内"create"或是"copy"一个对象, 但不调用CFRelease,这会导致count永远不能为0,也就是说当你不再需要这个对象的时候,这个对象的资源也是不会被释放的,这样就导致了内存泄露,因此,在任何地方使用了"create"和"copy"类的函数,都要记得在适当的时候进行CFRelease.

例子1:

- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    {

        CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);

        

        NSLog(@"ori string is :%@", ori);

        CFRelease(ori);

    }

    

}

输出结果:

2016-12-15 15:23:27.246 arctest[68228:4877964] ori string is :hello world

例子2:

- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    {

        CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);

        NSLog(@"before release ori address is :%p", ori);

        CFRelease(ori);

        NSLog(@"after release ori address is :%p", ori);

        NSLog(@"ori string is :%@", ori);

        

    }

    

}

输出结果:

2016-12-15 15:36:11.892 arctest[68889:4885433] before release ori address is :0x60000003f8e0

2016-12-15 15:36:11.892 arctest[68889:4885433] after release ori address is :0x60000003f8e0


当nslog打印输出的时候,进程core了,这个是因为在打印之前已经对ori做了CFRelease处理,由于在CFRelease之前没有对ori的任何引用,也就是说引用计数器count的值一直是1,当CFRelease之后,这个count就变成了0,ARC就释放了ori的资源,导致nslog访问ori对象时core了,这里注意,通过打印日志可以看出,ARC对CF指针的处理并不像cocoa一样,cocoa的对象的指针会被ARC设置成0,但CF的指针还是不变的,也就是说在ARC处理之后,这个指针变成了一个野指针,如果有判断if(ori),这样的语句,会出很大的问题.(有同学说,CFStringRef看字面意思并不是指针啊,更像是一个对象,其实你可以在xcode下看一下它的定义typedefconststruct CF_BRIDGED_TYPE(NSString) __CFString * CFStringRef;其实就是一个指针).

对于上面的代码更优雅一点的处理如下:

- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    {

        CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);

        NSLog(@"before release ori address is :%p", ori);

        CFRelease(ori);

        ori = nil;

        NSLog(@"after release ori address is :%p", ori);

        NSLog(@"ori string is :%@", ori);

        

    }

    

}

输出结果:

2016-12-15 15:37:19.868 arctest[68958:4886617] before release ori address is :0x608000220900

2016-12-15 15:37:19.868 arctest[68958:4886617] after release ori address is :0x0

2016-12-15 15:37:19.872 arctest[68958:4886617] ori string is :(null)

这样处理就不会core了.同时也避免了if语句的问题.


2.通过CF提供的包含有"get"关键字的函数名获取到的是对象的引用但并不增加count的值,也就是说不需要对这个变量CFRelease,要想使用get获取对象的拥有权,必须调用CFRetain函数.

3.说一下CF(Core Foundation)中的"="赋值语句.

CF中的赋值语句其实就是一个"浅引用",不会增加对象的count,(这个和cocoa中的"="不一样, cocoa中的赋值语句会增加count)这样很危险,很可能在使用这种引用的变量的时候,原始对象已经被释放了. 要解决这种问题,需要使用CFRetain, 在确定不在需要引用之后,要使用CFRelease放弃引用,如果Retain过,但没有release的话,会导致count永远不会为0,导致不需要对象的时候,不能得到正常的释怀资源, 会造成内存泄露.

例子1:

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    {

        CFStringRef ori = CFStringCreateWithCString(kCFAllocatorDefault,"hello world", kCFStringEncodingISOLatin1);

        NSLog(@"before release ori address is :%p", ori);

        CFStringRef dest = ori;

        //CFRetain(dest);

        CFRelease(ori);

        

        //ori = nil;

        NSLog(@"after release dest address is :%p", dest);

        NSLog(@"dest string is :%@", dest);

        

    }

    

}

输出结果:

2016-12-16 14:36:39.458 arctest[2254:236748] before release ori address is :0x600000029960

2016-12-16 14:36:39.458 arctest[2254:236748] after release ori address is :0x600000029960

2016-12-16 14:36:39.459 arctest[2254:236748] dest address is :0x600000029960

说明CF中资源被释放后不会把指针设置成0,这个时候ori和dest都是一个野指针.上面的代码在打印dest中的信息时core了.

解决方案:

- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    {

        CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);

        NSLog(@"before release ori address is :%p", ori);

        CFStringRef dest = ori;

        CFRetain(dest);

        CFRelease(ori);

        ori = nil;

        NSLog(@"after release ori address is :%p", ori);

        NSLog(@"dest address is :%p", dest);

        NSLog(@"dest string is :%@", dest);

        CFRelease(dest);

        dest = nil;

    }

    

}

输出结果:

2016-12-16 14:43:28.538 arctest[2321:246016] before release ori address is :0x60000003b420

2016-12-16 14:43:28.538 arctest[2321:246016] after release ori address is :0x0

2016-12-16 14:43:28.538 arctest[2321:246016] dest address is :0x60000003b420

2016-12-16 14:43:28.538 arctest[2321:246016] dest string is :hello world


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值