iOS内存管理

iOS的内存管理,MRC ARC,具体的规则都能了解一些的,知其然,更要知其所以然。

 分享下内存分配的预备知识:

一个由C/C++编译的程序会分为5个部分:栈区,堆区,全局区(静态区),文字常量区,程序代码区。  

其中只有堆区是需要程序员管理的,那么内存管理核心就是堆区内存管理。

iOS Object-C是类C语言,那就先要了解C语言的内存,C语言动态内存分配提供malloc, calloc, realloc, free等函数,从操作系统中获取、使用和释放内存。

由基本的这些函数延伸出来的内存策略大致有:引用计数、内存池、垃圾收集等策略。

iOS采用的策略为引用计数,引用计数是一种半自动的内存管理技术,需要编程支持。

引用计数中,共享数据结构中有一个域来标识"引用"结构的次数,当程序指令中有一个指向此数据结构指针时,该引用计数+1。通俗来讲,它正在被存储在多少个位置上。

对它使用后,引用计数-1,此时检查计数是否为0。(为0,释放内存)。

 引用计数的好处:防止正在使用数据结构是释放该结构。

 引用计数的坏处:难以处理发生循环引用的数据结构。

实现引用计数需要两个函数:增加计数函数,减少计数函数(需判断为0 释放内存);对应iOS增加计数的为alloc,retain 减少计数为release 。

看下代码:

struct obj_layout {
    NSUInteger retained;
};
+ (id) alloc
{
    int size = sizeof(struct obj_layout) + 对象大小;
    struct obj_layout *p = (struct obj_layout *)calloc(1,size);
    return (id)(p+1);
}


- (id) retain
{
    NSIncrementExtraRefCount(self);
    return self;
}
inline void
NSIncrementExtraRefCount (id anObject)
{
    if (((struct obj_layout *)anObject)[-1].retained == UINT_MAX – 1)
        [NSException raise: NSInternalInconsistencyException
            format: @"NSIncrementExtraRefCount() asked to increment too far");
    ((struct obj_layout *)anObject)[-1].retained++;
}

- (void) release
{
    if (NSDecrementExtraRefCountWasZero(self))
        [self dealloc];
}
BOOL
NSDecrementExtraRefCountWasZero (id anObject)
{
    if (((struct obj_layout *)anObject)[-1].retained == 0) {
        return YES;
    } else {
        ((struct obj_layout *)anObject)[-1].retained--;
        return NO;
    }
}

这就是MRC下,alloc/retain 一定对应 release的原理,CFCreatObject 对应CFRelease。

在说下apple牛逼的ARC,自动引用计数,并不是垃圾回收机制,注意iOS编码中的内存管理一定是引用计数,改动只是针对OC对象的,之所以这么做,是因为它还做不到C结构的自动计数,在编译中加了相关的优化而已,替开发者添加相关代码达到内管隐式管理,这就带来了一个比较麻烦的问题,需要区分对待OC和CF对象,当然apple都给你想到了,怎么样在ARC下的内存管理。如下:

1、修饰符,__strong, __weak,__unsafe_unfetained,_autoreleasing。

__strong是缺省的修饰符,在不适用任何修饰符的情况下,默认此修饰符,编译器自动为修饰符修饰的对象生成release代码。

例如:NSString *string = [NSString alloc]init];    等价于 NSString  __strong *string = [NSString alloc]init]; 

__weak修饰符修饰的对象,运行时系统会记录该指针,对象释放时,此指针置为nil,最大用处在消除循环引用和避免程序崩溃。

__unsafe_unfetained修饰的对象,在对象释放时,不会将指针置为nil, 之所以有为了支持iOS/OS X。

_autoreleasing修饰符修饰的对象指针注册在自动释放池,id指针(或者对象指针的指针)默认为__autoreleasing  函数参数以及返回值为__autoreleasing

2、ARC规则 

   retain release retainCount autorelease不会再用(包括内部调用的  NSAllocateObject NSDeallocateObject),编译器也不会通过;

  不可以显式调用dealloc,

  用@autoreleasepool{}块代替NSAutoreleasePool;

  对象类型变量不能在C的struct/unin作为成员,

  id void*显示转换,__bridge __bridge_retained __bridge_transfer 涉及所有权转换问题;







    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值