1、什么情况下需要内存管理?
任何继承了NSObject的对象,对基本数据类型无效。
2、内存管理的原理?
每个对象内部都保存了一个与之相关联的整数,称为引用计数器。
当使用alloc、new或者copy创建一个对象时,对象的引用计数器被设置为1。
给对象发送一条retain消息,引用计数器值+1。
给对象发送一条release消息,引用计数器值-1。
当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收,OC也会自动向对象发送一条dealloc消息。
可以给对象发送retainCount消息获得当前的引用计数器值。
3、什么叫野指针?
即当计数器已经为0了,还继续release,访问了不属于你的内存,这样就叫野指针错误。
防止出现野指针的做法:尽量不要在调用的文件中写释放,不然会出现一个地方释放了该对象,在另一个方法又出现调用的情况,这样就会出现野指针。所以最好在创建语句的文件中dealloc方法写release语句,因为无论谁创建了一个对象,最终销毁时都要调用一次dealloc方法。这样别人只管调用,不用管内存释放的问题了,可以保证内存不浪费。
例子如下:
在Book.h文件中
#import<Foundation/Foundation.h>
@interface Book :NSObject
@property int price;
@end
在Book.m文件中
在XCode4.5版本以上编写:只需在.h文件中写@property语句即可,不用在.m文件中写@sythesize了。
#import<Foundation/Foundation.h>
@implementation Book
@end
在Student.h文件中
#import<Foundation/Foundation.h>
@implementation Student
-(void)setBook : (Book *) book;
-(Book *)book;
-(void)readBook;
@end
在Student.m文件中
#import<Foundation/Foundation.h>
@implementation Student
#pragram mark -getter和setter
-(void) setBook : (Book *) book
{
_book = [book retain];
}
-(Book *) book{
return _book;
}
-(void)readBook{
NSLog(@”调用了readBook方法。”);
}
#pragma mark 回收对象
-(void)dealloc{
[self.book release];//等价于[_book release];即销毁book对象
[super dealloc];
}
@end
在main.m文件中调用
#import<Foundation/Foundation.h>
#pragram mark 私有方法
void test(Student *stu){
Book *book = [[Book alloc] initWithPrice:3.5];//创建一个对象,计数器+1
stu.book = book; //调用一次set方法,该方法内有retain操作,所以计数器会+1
[book release]; //释放一次,计数器 -1,所以调用完该方法,book对象还可以继续使用
}
void test1(Student *stu){
[stu readBook];//因为book对象还没被销毁,计数器不为0,所以这样调用就不会出现空指针
}
int main(int argc,const char * argv[])
{
@autoreleasepool{
Student *stu = [[Student alloc] initWithAge:10];//创建一个对象,Student计数器为1
test(stu);
test1(stu);
[stu release];//释放stu对象,同时也会调用stu的dealloc方法,该方法内部同时也会释放book对象,所以最终book对象也会被销毁掉,从而不会出现内存泄露的问题。
}
return 0;
}
第二种情况:当有两个指针对象都调用同一个变量的情况,内存释放例子如下:
在Book.h文件中
#import<Foundation/Foundation.h>
@interface Book :NSObject
@property int price;
@end
在Book.m文件中
在XCode4.5版本以上编写:只需在.h文件中写@property语句即可,不用在.m文件中写@sythesize了。
#import<Foundation/Foundation.h>
@implementation Book
@end
在Student.h文件中
#import<Foundation/Foundation.h>
@implementation Student
-(void)setBook : (Book *) book;
-(Book *)book;
-(void)readBook;
@end
在Student.m文件中
#import<Foundation/Foundation.h>
@implementation Student
#pragram mark -getter和setter
-(void) setBook : (Book *) book
{
[_book release];//先释放掉原来的book对象,即book1,如果缺少这句,会造成原来的对象变成野指针,没有释放。
_book = [book retain];//然后再把book2对象赋值上去。
}
-(Book *) book{
return _book;
}
-(void)readBook{
NSLog(@”调用了readBook方法。”);
}
#pragma mark 回收对象
-(void)dealloc{
[self.book release];//等价于[_book release];即销毁book对象
[super dealloc];
}
@end
在main.m文件中调用
#import<Foundation/Foundation.h>
#pragram mark 私有方法
void test(Student *stu){
Book *book = [[Book alloc] initWithPrice:3.5];//创建一个对象,计数器+1
stu.book = book; //调用一次set方法,该方法内有retain操作,所以计数器会+1
[book release]; //释放一次,计数器 -1,所以调用完该方法,book对象还可以继续使用
Book *book2 =[[Book alloc] initWithPrice:4.5];
stu.book = book2;
[book2 release];
}
void test1(Student *stu){
[stu readBook];//因为book对象还没被销毁,计数器不为0,所以这样调用就不会出现空指针
}
int main(int argc,const char * argv[])
{
@autoreleasepool{
Student *stu = [[Student alloc] initWithAge:10];//创建一个对象,Student计数器为1
test(stu);
test1(stu);
[stu release];//释放stu对象,同时也会调用stu的dealloc方法,该方法内部同时也会释放book对象,所以最终book对象也会被销毁掉,从而不会出现内存泄露的问题。
}
return 0;
}