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

Autorelease

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

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

- (NSMutableArray*)createArrayNoAutorelease{
id arr = [NSMutableArray arrayWithCapacity:3];
return arr;
} - (NSMutableArray*)createArrayAutorelease{
return [NSMutableArray arrayWithCapacity:3];
}

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

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

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方法,如下:

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中。我们可以使用:

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

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

  1. 理解 iOS 的内存管理

    远古时代的故事 那些经历过手工管理内存(MRC)时代的人们,一定对 iOS 开发中的内存管理记忆犹新.那个时候大约是 2010 年,国内 iOS 开发刚刚兴起,tinyfool 大叔的大名已经如雷贯耳 ...

  2. 说说iOS与内存管理(上)

    http://www.cocoachina.com/ios/20150625/12234.html 说起内存管理,看似老生常谈,而真正掌握内存管理的核心其实并不简单.ARC/MRR以及“谁分配谁就负责 ...

  3. iOS的内存管理和引用计数规则、Block的用法以及三种形式(stack、malloc、global)

    学习内容 iOS的内存管理和引用计数规则 内存管理的思考方式 自己生成的对象自己持有 非自己生成的对象自己也能持有 自己持有的对象不需要时释放 非自己持有的对象不能释放 ARC有效时,id类型和对象类 ...

  4. iOS内存管理 ARC与MRC

    想驾驭一门语言,首先要掌握它的内存管理特性.iOS开发经历了MRC到ARC的过程,下面就记录一下本人对iOS内存管理方面的一些理解. 说到iOS开发,肯定离不开objective-c语言(以下简称OC ...

  5. IOS基础之 (十一) 内存管理 ARC

    一 内存管理 1. set 方法内存管理的相关参数 retain: release旧值,retain新值(值适用于OC对象) assign:直接赋值(set方法默认,适用于非OC对象类型,即基本数据类 ...

  6. OC内存管理(ARC)

    1.什么是ARC Automatic Reference Counting,自动引用计数,即ARC,可以说是WWDC2011和iOS5所引入 的最大的变革和最激动人心的变化.ARC是新的LLVM 3. ...

  7. iOS - OC 内存管理

    1.OC 基本内存管理模型 1.1 自动垃圾收集 在 OC 2.0 中,有一种称为垃圾收集的内存管理形式.通过垃圾收集,系统能够自动监测对象是否拥有其他的对象,当程序执行需要空间的时候,不再被引用的对 ...

  8. 总结 IOS 7 内存管理

    [iOS7的一些总结].iOS中的内存管理 我们知道,为了更加方便地处理内存管理问题,将开发人员从繁琐的内存的分配和释放工作中解放出来而专注于产品和逻辑,iOS提供了一种有效的方法, 即自动引用计数A ...

  9. iOS的内存管理

    在Objective-C 这种面向对象的语言里,内存管理是个重要的概念.要想用一门语言写出内存使用效率高而且又没有bug的代码,就得掌握其内存管理模型的种种细节. 一旦理解了这些规则,你就会发现,其实 ...

随机推荐

  1. Flex的 Event中属性currentTarget与target的区别

    Flex的 Event中属性currentTarget与target的区别 1.区别 (1)currentTarget是事件的处理对象(event processor) (2)target是事件的调用 ...

  2. Flex中对表格中某列的值进行数字格式化

    1.问题背景 一般的,表格中展示的比率,对比率的处理是:保留两位小数,并向上保留 2.实现实例 <?xml version="1.0" encoding="utf- ...

  3. javaWeb学习之Listener监听

    ] 一.监听器Listener javaEE包括13门规范 在课程中主要学习 servlet技术 和 jsp技术 其中 servlet规范包括三个技术点:servlet  listener  filt ...

  4. 简单bfs(hdu2612)

    #include<stdio.h>#include<string.h>#include<queue>#define INF 0x3f3f3f3fusing name ...

  5. MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 转

    MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决   在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等. ...

  6. Linux命令top 详解

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法. top - 01:06:48 up 1:22, 1 ...

  7. Splay入门解析【保证让你看不懂(滑稽)】

    BST真是神奇的东西... 而且种类好多呀... 我这个蒟蒻只学会了splay orzCJ老爷,各种树都会 好好好,不说了,直接说splay. 不知道splay是啥,,你也要知道平衡树是啥... 平衡 ...

  8. 【BZOJ2754】喵星球上的点名(AC自动机)

    [BZOJ2754]喵星球上的点名(AC自动机) 题面 BZOJ 题解 友情提示:此题请不要在cogs上提交,它的数据有毒 对于点名串构建\(AC\)自动机 然后把名字丢进去进行匹配, 大力统计一下答 ...

  9. [BZOJ2761] [JLOI2011] 不重复数字 (set)

    Description 给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 ...

  10. token的时限多长才合适?

    在使用JWT时,一个让人纠结的问题就是"Token的时限多长才合适?".对此,Stormpath的这篇文章给出了一个可供参考的建议: 面对极度敏感的信息,如钱或银行数据,那就根本不 ...