iOS之内存管理(ARC)

iOS的内存管理,相信大家都不陌生,之前是使用的MRC,由开发人员手动来管理内存,后来使用了ARC,来由系统管理内存。本文主要讲讲Autorelease,Core Foundation对象在内存管理方面要注意的地方。

Autorelease

提到内存管理,就不得不提autorelease,虽然我们平时开发中很少会感知到它的存在。autorelease就是自动释放的意思,如果变量使用autorelease来修饰,就表明变量的释放由系统来完成。

autoreleasepool是由runloop在开启或者唤醒的时候创建的,当runloop进入睡眠或者释放掉的时候,autoreleasepool会给pool中的所有对象发送release消息。那么,由此便引申出一个问题,如果runloop不进入睡眠或者不释放(例如:主线程,或者某些常驻线程),pool里面的对象也便不会被释放,他们会堆积在内存中,但是系统会做一些优化,如下:


1

2

3

4

5

6

7

8

- (NSMutableArray*)createArrayNoAutorelease{

    id arr = [NSMutableArray arrayWithCapacity:3];

    return arr;

}

- (NSMutableArray*)createArrayAutorelease{

    return [NSMutableArray arrayWithCapacity:3];

}

上面的两个方法都是表明的要返回NSMutableArray这个对象,但是两种写法不同,系统做的处理也不相同。

我们先调用第一个方法 createArrayNoAutorelease方法,然后使用xcode的Product->Perform Action->Assemble xxx来看看,生成如下代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

Lfunc_begin1:

....前面省略

    bl  _objc_retainAutoreleasedReturnValue

    .loc    2 56 14                

    str r0, [sp, #4]

    .loc    2 57 12 is_stmt 1      

    ldr r0, [sp, #4]

    bl  _objc_retain

    add r1, sp, #4

    movs    r2, #0

    .loc    2 58 1                 

    str r0, [sp]                @ 4-byte Spill

    mov r0, r1

    mov r1, r2

    bl  _objc_storeStrong

    ldr r0, [sp]                @ 4-byte Reload

    .loc    2 58 1 is_stmt 0       

    add sp, #16

Ltmp3:

    pop.w   {r7, lr}

    b.w _objc_autoreleaseReturnValue

Ltmp4:

Lfunc_end1:

其中 objc_retainAutoreleasedReturnValue和objc_autoreleaseReturnValue主要用于优化程序运行。本来应该将返回的对象注册到autoreleasepool中,但是有了这两个函数,就可以不将对象注册到autoreleasepool中,而是直接传递给调用方,这是性能调优的一个举措。

我们再来看看调用createArrayAutorelease方法,如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Lfunc_begin0:

... 省略

    bl  _objc_retainAutoreleasedReturnValue

    add r1, sp, #4

    movs    r2, #0

    .loc    2 44 8                

    str r0, [sp, #4]

    .loc    2 49 1 is_stmt 1       

    mov r0, r1

    mov r1, r2

    bl  _objc_storeStrong

    add sp, #24

    pop {r7, pc}

Ltmp1:

Lfunc_end0:

现在对象被注册到了autoreleasepool中。我们可以使用:


1

po [NSAutoreleasePool showPools]

来看看当前autoreleasepool的状况,会发现多出了一个对象,如下图:

(我只截取了一部分)

注意:对于alloc/new/copy/mutableCopy这样的方法作为返回对象,编译器会将他们优化为createArrayNoAutorelease相同的情况

关于autoreleasepool的内部结构,实现原理等,可以参看:

http://www.cocoachina.com/ios/20150610/12093.html

Core Foundation

Core Foundation对象是一组由c语言接口,可以跟Foundation框架的OC对象相互转换。

要搞清楚Core Foundation对象的内存管理,就需要搞清楚:__bridge, __bridge_retained, __bridge_transfer; CFRetain(), CFRelease() 这几个关键词的概念。

CFRetain(), CFRelease() :Core Foundation对象的内存管理方式,跟之前MRC时代的retain和release很像。

    {
        CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, "test", kCFStringEncodingUTF8);
        NSLog(@"%@", str);
        CFRelease(str);
    }

注意:这里要调用CFRelease(str)方法,不然会有内存泄漏。

__bridge:只做类型转换,不修改对象持有者。如下:

    {
        CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, "test", kCFStringEncodingUTF8);
        NSString *obj = (__bridge NSString*)str;
        NSLog(@"%@", obj);
//        CFRelease(str);
    }

对于从CF转换为OC对象,一定要调用CFRelease(str)方法,不然会有内存泄漏,因为只是做了简单的指针地址变换,str仍然没有释放。

来看一个野指针的例子:

    CFMutableArrayRef cfObject = NULL;
    {
        id obj = [[NSMutableArray alloc] init];
        cfObject = (__bridge CFMutableArrayRef)obj;
        CFShow(cfObject);
    }
    CFRelease(cfObject);

因为__bridge不持有obj对象,所以当大括号结束以后,obj被释放,cfObject就成为了野指针,在调用CFRelease方法时就会引发程序崩溃。

__bridge_retained:用于将OC对象转换为CF对象,持有者也发生改变,需要调用CFRelease方法。

__bridge_transfer:将CF对象转换为OC对象,同时将对象持有权交给ARC,不需要调用CFRelease方法,如下:

    {
        CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, "test", kCFStringEncodingUTF8);
        NSString *obj = (__bridge_transfer NSString*)str;
        NSLog(@"%@", obj);
//        CFRelease(str);
    }

所以在使用CF对象时,要特别注意内存问题。

参考文章:

https://yq.aliyun.com/articles/58964

https://juejin.im/entry/579bfdfe5bbb500064d18aca

原文地址:https://www.cnblogs.com/scode2/p/8671214.html

时间: 2024-12-11 08:09:36

iOS之内存管理(ARC)的相关文章

ios 自动内存管理 ARC

今天在公司爆出一个 BUG,导致5000+crash. 大致是 UIKit 中的 delegate 访问了已经释放了的界面,也就是使用了野指针导致 crash. 回来演示了一下发现 @property (nonatomic, assign) id<MyCellDelegate> delegate;//1 @property (nonatomic, weak) id<MyCellDelegate> delegate;//2 大部分的 UIKit 的 delegate 都是如1的声明

iOS开发之oc(十二)--内存管理ARC

(一)自动内存管理 --ARC 1>简单点说就是让编译器完成堆空间的引用计数的加减,自动释放,程序员不再写retain 和release等方法 2>OC的自动内存管理不同于java 的垃圾回收,而是在预处理是直接在应该保留的地方加上retain,在应该改释放的地方加上release,是直接添加代码 3>从效率上讲,ARC优于手动内存管理 2.1.1 ARC 的局限性 1>使用ARC可能因为代码的不规范,导致内存提前释放 2>导入第三方库,或者导入旧代码,这些代码不支持ARC

说说iOS与内存管理(上)

http://www.cocoachina.com/ios/20150625/12234.html 说起内存管理,看似老生常谈,而真正掌握内存管理的核心其实并不简单.ARC/MRR以及“谁分配谁就负责释放”这种基本原则是很重要的,但不是本文要讨论的重点.之前本人还没在小站发过相关的文章,本篇文章中,我本人是想结合实际开发和调试中遇到的一些细节问题,来谈谈iOS的内存管理内在机制和调试方法. 上一篇文章已经是4月份的了,时间飞快又过去了好久,小站5月份没有文章更新,罪过罪过.最近小站的站长我又转换

理解 iOS 的内存管理

理解 iOS 的内存管理 远古时代的故事 那些经历过手工管理内存(MRC)时代的人们,一定对 iOS 开发中的内存管理记忆犹新.那个时候大约是 2010 年,国内 iOS 开发刚刚兴起,tinyfool 大叔的大名已经如雷贯耳,而我还是一个默默无闻的刚毕业的小子.那个时候的 iOS 开发过程是这样的: 我们先写好一段 iOS 的代码,然后屏住呼吸,开始运行它,不出所料,它崩溃了.在 MRC 时代,即使是最牛逼的 iOS 开发者,也不能保证一次性就写出完美的内存管理代码.于是,我们开始一步一步调试

总结 IOS 7 内存管理

[iOS7的一些总结]5.iOS中的内存管理 我们知道,为了更加方便地处理内存管理问题,将开发人员从繁琐的内存的分配和释放工作中解放出来而专注于产品和逻辑,iOS提供了一种有效的方法, 即自动引用计数ARC.采用了ARC之后,绝大部分内存管理的问题就不需要我们继续操心了.但是从另一个方面讲,这个方便的工具也助长了程序员的懒惰情 绪,很多新手和学生甚至连引用计数的含义都不清楚.的确,这部分内容相对比较难以理解,不过如果能深刻地领悟之后将会是未来学习和开发中的强大助推器. 1.关于对象所有权的概念:

iOS内存管理 ARC与MRC

想驾驭一门语言,首先要掌握它的内存管理特性.iOS开发经历了MRC到ARC的过程,下面就记录一下本人对iOS内存管理方面的一些理解. 说到iOS开发,肯定离不开objective-c语言(以下简称OC).OC的内存管理机制叫做引用计数,就是一块内存地址可以同时被多个对象引用,每引用一次,引用计数都会递增1,当对象每解除一次引用,引用计数就会递减1,直到引用计数为0时,系统才会讲这块内存地址回收释放掉,这与C/C++语言有些不同,但是它们都遵守同一个内存管理法则:谁申请,谁释放. 在早些时候,iO

iOS 5编程 内存管理 ARC技术概述

Automatic Reference Counting (ARC) 是一个编译期的技术,利用此技术可以简化Objective-C编程在内存管理方面的工作量. 这里我把此技术翻译为自动内存计数器管理技术,下图是使用和不使用此技术的Objective-C代码的区别. ARC技术是随着XCode4.2一起发布的,在缺省工程模板中,你可以指定你的工程是否支持ARC技术,如果你不指定工程支持ARC技术,在代码中你必须使用管理内存的代码来管理内存. 概述 自动计数(ARC)是一个编译期间工作的能够帮你管理

iOS内存管理-ARC

一:什么是ARC,ARC是iOS5引入的内存管理机制,即自动引用计数.相对于iOS早期的MRC即手动管理计数,在内存管理上更加高效和简便. 例如在一个函数中,初始化一个对象或者去持有一个对象则引用计数+1,但不再使用这个对象时,引用计数将会-1.这个过程如果使用MRC来操作,则需要手动写入retain和release,而ARC则优化了这个过程. 二:ARC的核心思想: 1.自己生成的对象,自己持有 2.非自己生成的对象,自己可以持有 3.自己持有的对象不在需要时,需要对其进行释放 4.非自己持有

iOS基础 ----- 内存管理

Objective-C 的内存管理方式有引用计数机制,垃圾回收机制,自动释放池.有alloc,就有释放.iOS应?程序出现Crash(闪退),90%的原因是因为内存问 题.在?个拥有数?个甚?是上百个类的?程?,查找内存问 题极其困难,学会内存管理,能帮我们减少出错的?率.内存问题体现在两个??:内存溢出.野指针异常. 引用计数器 在Xcode4.2及之后的版本中由于引入了ARC(Automatic Reference Counting)机制,程序编译时Xcode可以自动给你的代码添加内存释放代