一、c中程序的内存区域分配
1、栈区(stack)— 存放函数的参数值,局部变量的值等,由编译器自动分配释放。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(data段中的静态区), 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(bbs段),程序结束后由系统释放。
4、文字常量区 —常量字符串就是放在这里的,程序结束后由系统释放。
5、程序代码区—存放函数体的二进制代码。
栈区存放一些基础类型,是一块连续存储的空间,遵循先进后出的原则,但是当数据量比较大的时候,降低性能,我们会把地址存放在栈中,数据存放在堆中,所以说系统不会自动释放堆中的内存的,希望我们程序员自己释放的。
二、MRC
1、引用计数器
我们知道当生成的对象还有被引用时,就不能被释放,那这个对象什么时候被释放呢,OC在内存管理上用了引用计数器(retain count), 在对象内部保存一个数字,当new copy(mutablecopy) retain alloc的时候retaincount+1;当调用release时retaincount-1;当retain count等于0的时候,系统才会调用dealloc方法来销毁对象。
2、内存管理原则:谁创建谁释放,谁retain谁释放
配对原则,retain和release是配对的,retain>release内存泄露
3、set方法
- (void)setClass:(ClassA*)class {
[class retain];
[_class release];
_class=class;
}或
- (void)setClass:(ClassA*)class {
if(_class!=class){
[_classrelease];
[classretain];
_class=class;
}
}
4、属性与内存管理
@property实际上是getter和setter,@synthesize是合成这2个方法。
5、自动释放池
自动释放池相当于半自动的释放,存储在自动释放池的对象,在自动释放池销毁时,会自动调用该对象的release方法,故将对象存储在自动释放池中,就不需要再写release,相当于延迟释放.
intmain(intargc,constchar* argv[]) {
@autoreleasepool{
ClassA*a=[[ClassAalloc]init];
[aautorelease];
a.num=@"111";//这时候还没有释放
return0;
}
}
只有在自动释放池中调用了对象的autorelease方法,这个对象才会被存储到这个自动释放池之中,当自动释放池结束的时候.仅仅是对存储在自动释放池中的对象发送1条release消息 而不是销毁对象.
三、ARC
1、ARC是编译时编译器会自动的在合适的地方插入retain、release、autorelase代码;编译器自动为对象做引用计数.而大大节约了开发者人员的工作。
2、属性与内存管理
strong,和copy相当于mrc会在set,get的时候将引用计数加一,咱们要注意避免循环引用,造成内存泄露,将其中一个用weak.
3、ARC只对3类 retainable object pointers(ROPs)起作用:
Block 指针;
Objective-C 对象指针;
_attribtue_((NSObject))标记的typedef .
所有其他的指针如 char*, CF对象如 CFStringRef,malloc c array等,都不是ARC支持的,需要自己手动处理。
4、Objective-C和 Core Foundation 对象相互转换
Core Foundation是用c提供的接口,可以和OC的一些对象进行相互的转换。
CFStringRef aCFString = (CFStringRef)aNSString;
NSString *aNSString = (NSString *)aCFString;
在MRC的情况下相互转换之后释放就好,但是在ARC的情况下怎么考虑呢
1. __bridge_retained 或者 CFBridgingRetain()
__bridge_retained 或者 CFBridgingRetain() 将Objective-C对象转换为Core Foundation对象,把对象所有权桥接给Core Foundation对象,后续需要开发者使用CFRelease或者相关方法手动来释放对象。
2. __bridge_transfer 或者 CFBridgingRelease()
__bridge_transfer 或者 CFBridgingRelease() 将非Objective-C对象转换为Objective-C对象,同时将对象的管理权交给ARC,开发者无需手动管理内存。
3. __bridge
__bridge 只做类型转换,不改变对象所有权,是Core Foundation手动释放,不是就自动释放
四、参考