在Objective-C编写程序时, 提供了两种内存管理机制MRC(Manual ReferenceCounting)和ARC(Automatic Reference Counting), ARC是系统自动管理内存,MRC则需要我们自己手动管理内存问题。ARC是在iOS 5以后才推出的,就是在我们编写程序的时候,自动的加了retain和release。
在MRC内存管理机制中,我们经常会遇到内存过度释放或是内存泄露的问题,即使是在ARC的内存管理机制下,我们也会遇到内存过度释放或是内存泄露的问题。
在Objective-C编写程序时,有两种影响引用计数的方法:一是,增加引用计数: alloc, retain, copy [在方法里遇到这三个关键字,最后就要写release];二是,减少引用计数: release, autorelease。
增加引用计数的方法: alloc 开辟一块内存,将内存的引用计数从0变为1;retain 将现有的内存引用计数+1 [可反复使用];copy会新开辟一块内存和原来的内存大小,存储内容一致,保持原有的引用计数不变,新的内存引用计数变为1,copy的对象,必须实现NSCopying协议。
减少引用计数的方法:release 让对象的引用计数 -1;autorelease 在将来的某个地方 对这个对象引用计数 -1,如果被autorelease方法调用,内存不会当时被 -1,autorelease一般都写在自动释放池中,
在MRC内存管理机制中,对引用计数的管理要保持一个平衡,确保有一次+1就有一次-1。定义了属性,要及时对属性进行内存管理,在最后的dealloc中要对(retain 或 copy)的属性进行release。
@interface Person ()
@property(nonatomic,retain) NSString *name;
@property(nonatomic,assign) NSInteger number;
@property(nonatomic,retain) NSString *sex;
@property(nonatomic,copy) NSString *hobby;
@end
- (void)dealloc
{
// 对属性进行内存管理
// 当一个对象被释放的时候 要把这个对象持有的所有对象(retain copy)进行一次release
[_name release];
[_sexrelease];
[_hobby release];
[super dealloc];
}
在编写程序中,程序一直因为内存泄露问题而奔溃,却找不到内存是在哪里发生了泄露,可以使用以下一个方法去查找是在哪里发生了内存泄露(此方法只在模拟器上试用过)1.打开电脑上的活动监视器和终端。
2.运行你的程序,在活动监视器里搜索你的软件名字,找到对应的PID 例如:46757
3.当你的程序奔溃的时候后面会有一个地址,例如:0x7f8bcd344430
4.在你的终端里输入:sudo malloc_history PID奔溃时的地址
bogon:~ dlios$ sudo malloc_history46757 0x7f8bcd344430
5.点回车,会弹出输入密码的命令,输入你开机密码,这时就会弹出一大段信息,这时只需要找到以下这段
Invalid connection: com.apple.coresymbolicationd
ALLOC 0x7f8bcd344430-0x7f8bcd344717 [size=744]: thread_10cfa2310 |start | main | UIApplicationMain | GSEventRunModal | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | _UIApplicationHandleEventQueue | _UIApplicationHandleEventFromQueueEvent | -[UIApplication sendEvent:] | -[UIWindow sendEvent:] | -[UIWindow _sendTouchesForEvent:] | -[UIControl touchesEnded:withEvent:] | -[UIControl _sendActionsForEvents:withEvent:] | -[UIApplication sendAction:to:from:forEvent:] | -[UIApplication sendAction:to:from:forEvent:] | -[MainViewController search:] | _objc_rootAlloc | class_createInstance | calloc | malloc_zone_calloc
直接在最后找到 | _objc_rootAlloc | class_createInstance | calloc | malloc_zone_calloc ,这些代码前面的| -[MainViewController search:] |基本就是你程序奔溃的原因。如果第一次在终端输入命令时,弹出 “ The target process has no stack logs. Run it with the MallocStackLogging environment variable set to get stack logs.” 多运行程序,找到奔溃地址,重复上诉步骤。