iOS内存管理
来源:互联网 发布:唱杀破狼的js是谁 编辑:程序博客网 时间:2024/06/05 05:55
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);
}
{
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 涉及所有权转换问题;
- IOS 内存管理
- iOS内存 管理 一点
- ios内存管理
- IOS内存管理小结
- iOS内存管理
- 再论iOS内存管理
- iOS内存管理
- IOS 内存管理
- IOS内存管理
- IOS内存管理
- iOS内存管理
- ios 内存管理基础知识
- ios内存管理
- iOS 内存管理
- IOS内存管理详解
- iOS 内存管理总结
- ios内存管理
- ios 内存管理
- unity3d 使用Quaternion 类实现两个简单功能
- 宁坐在切糕车上哭 也不坐在宝马车里笑
- Android include 标签注意点
- UI_UIActionSheet、UIPageControl
- 100个iOS开发/设计面试题汇总
- iOS内存管理
- cocoapods在Ios项目中的安装和使用
- cocos2dx 由小到大弹出对话框
- 职场励志小故事——【强盗师徒】
- Redis介绍及常用命令
- albert1017 eclipse闪退解决
- Web Service
- 三个故事说穿了很多人
- 随笔20150326