您的位置:首页 > 其它

内存管理

2015-07-26 21:17 302 查看
——————————————————————————————

1-对象所有权:

      某个变量对指定的对象有使用权

    2-引用计数

      用来标识一个对象有几个使用者

    3-引用计数器

      记录使用者的个数的变量

      变量类型  unsigned  long

      方法  retainCount

      打印引用计数器的值   %lu

    4-引用计数器的作用

      作为对象是否要回收的依据

      如果为0  
要回收

      如果>0   
不要回收

    5-对引用计数器的操作

      向对象
发送 retain 消息        [obj  retain];

      使得对象的引用计数器+1

      向对象
发送 release 消息

      使得对象的引用计数器-1

    6-对象回收注意:

      一个对象如果回收的时候,系统自动的调用这个对象的 dealloc
方法

    MRC - 手动内存管理

    ARC - 自动引用计数管理 (默认的)

——————————————————————————————

//创建一个实例对象
       
Person *p = [Person
new];

        //Person *p = [[Person alloc]init];

    

        //对象引用计数器的值?

        //[p retainCount];
可以获得对象的引用计数器的值

        //对象创建完成后,默认的有一个所有者,就是他自己
       
NSUInteger n = [p
retainCount];
        [p
retain]; //
让引用计数期的值+1

        
       
NSLog(@"n = %lu",n); 
// 1

        

        //release
可以让对象的引用计数器的值 -1

        //如果对象的引用计数器的值
为 0

        //那么此时这个对象会被立即回收

        //会调用对象的 dealloc
方法(系统自动调用)

        
        [p
release];        
//0
       
//

        //NSLog(@"p.retainCount = %lu",[p retainCount]);  //
        [p
release];

———————————内存管理的原则———————————————————

 

   

   只要对象的引用计数不为0 ,这个对象就不能释放

   使用某个对象之前,先retain

   使用之后       
然后 relase

 

   口诀:

   1)谁创建,谁释放

 

   Person *p = [Person new];

   Person *p1 = p;

 

 

   [p release]; //谁创建谁release

 

   2)谁retain 
谁 release

 

 

    Person *p = [Person new];

    Person *p1 = p;

 

    [p1 retain];   //谁retain
谁release

    [p1 release];

 

 

    [p release]; //谁创建谁release

 

 

    野指针: 1)指针变量没有赋值   2)指向的空间已经不可用了

    空指针:
谁都不指向

 

    内存泄露:

 

    申请的空间,没有及时的释放

 

 

——————————————————————————————

内存泄露: 申请了空间,到程序结束,你都没有任何释放空间的操作

 

    单个对象的内存泄露问题

 

    1) 创建了对象以后,没有释放

 

    2) retain和release的个数不匹配问题

 

    3) 对象使用的过程中赋值了nil

 

    4) 在对象方法中不当的使用 retain

 

 

——————————————————————————————

 set方法的内存管理问题:

 

    1)对于基本数据类型的实例变量

    int _age,float _height;

    

     -(void)setAge:(int)age{

 

          _age = age;

     }

 

 

    2) 对于对象类型的set方法,应该按照如下去写

 

     Car *_car;

 

    -(void)setCar:(Car *)car{

 

        if(_car!=car){

 

         [_car release];

 

          _car = [car retain];

 

        }

 

    }

 

 

      -(void)dealloc{

    

          [_car release];

          [super dealloc];

 

      }

 

 */

——————————————————————————@perperty  参数————

 

   1) 什么时候使用 assign?

 

      基本数据类型的时候   int  float double  char 

      BOOL   struct   enum

 

 

   2) 什么时候使用retain 

 

      如果实例变量是 OC对象类型的时候,要使用 retain

 

      如果使用了retain 

      注意:
在 dealloc 方法,中要 release一次

——————————————————————————————

/*

 assign 直接赋值

 

 set方法没有使用retain

  

 -(void)setDog:(Dog *)dog{

 

     _dog = dog;

 

 }

 

 

 

 retain release旧的值,retain新的值

 

 -(void)setDog:(Dog *)dog{

 

    if(_dog != dog){

 

     [ _dog release];

     _dog = [dog retain];

 

 

    }

 

 }

 

 

——————————————————————————————

@property 参数分为三组

 

 

   1) 原子性

 

      atomic(默认)      -
线程安全

      nonatomic   - 线程不安全(如果程序中没有使用多线程,建议使用这个)

 

   2) 读写控制

 

      readwrite(默认)   -
生成get和set方法

      readonly    - 生成get方法

 

 

   3) set内存管理

 

      assign(默认)     retain   copy

 

 

——————————————————————————————

typedef struct T{

   
int hour;
   
int min;
   
int sec;

}Time;

//定义日期的结构体

typedef struct D{

    //定义年月日
   
int year;
   
int month;
   
int day;

    //定义时间
   
Time t;

}MyDate;

——————————————————————————————

@class 使用注意:

 

   @class 用在.h文件中

   用来告诉编译器这是一个类,这个类有哪些属性和行为,不会去立即检查

 

 

   .m中如果使用 @class引入的这个类的属性和方法,都需要重新导入一次

   这个类的头文件

——————————————————————————————

循环引用 一弱一强  assign  retain

——————————————————————————————

 

 高

   栈: 
局部变量

   堆: 
动态申请的空间  对象

   BSS: 没有初始化的全局变量和静态变量

   数据区:已经初始化的全局变量和静态变量,字符串常量

   代码区:程序编译后的代码的数据

 低

  //0x7fff5fbff7fc
       
int a = 10;  
// 局部变量

        //0x100000f82
       
char *s = "abc";
//字符串,数据区

        
       
NSLog(@"a addr = %p",&a); 
//高地址
       
NSLog(@"s addr = %p",s);  
//低地址

        

        //0x100001070
       
NSString *str1 = @"abc"; 
//@"abc" 字符串常量 ,在常量区
       
NSString *str2 = [NSString
stringWithString:@"def"];
       
NSString *str3 = [[NSString
alloc] initWithString:@"abc"];

        //0x100602420
       
//堆区
       
NSString *str4 = [NSString
stringWithFormat:@"aaa"];
       
NSString *str5 = [NSString
stringWithFormat:@"aaa"];
       
NSString *str6 = [[NSString
alloc] initWithFormat:@"bbbb"];

        
       
NSString *str7 = [[NSString
alloc] init];
        [str7
release];

        

        

        //此时因为str1
是一个常量,默认的引用计数是一个比较大的整数

        NSLog(@"str1 addr = %p,str1.rc = %lu",str1,str1.retainCount); 
//小

        NSLog(@"str2 addr = %p,str2.rc = %lu",str2,str2.retainCount); 
//小

        NSLog(@"str3 addr = %p,str3.rc = %lu",str3,str3.retainCount); 
//小

        NSLog(@"str4 addr = %p,str4.rc = %lu",str4,str4.retainCount); 
//小

        NSLog(@"str5 addr = %p,str5.rc = %lu",str5,str5.retainCount); 
//小

        NSLog(@"str6 addr = %p,str6.rc = %lu",str6,str6.retainCount); 
//小

        NSLog(@"str7 addr = %p,str7.rc = %lu",str7,str7.retainCount); 
//小
    }
   
return 0;


自动释放池

——————————————————————————————

/*

 自动释放池的作用:

   自动释放池结束的时候,会向自动释放池中所有的对象,发送一条 release

 自动释放池的使用步骤:

   1) 创建自动释放池

   2) 把对象加入到自动释放中

      怎么加入呢?

      对象调用 autorelease
方法,就把该对象加入到栈顶的自动释放中了

 */

#import <Foundation/Foundation.h>

#import "Car.h"
int main(int argc,
const char *argv[]) {

  @autoreleasepool {

   
Car *bigBen = [Car
new];

    [bigBen
run];

    [bigBen autorelease];
//把对象 bigBen
加入到自动释放池中

                          //         [bigBen release];
  }                      
// [bigBen release];

  return 0;

———————————沙盒———————————————————

 

    NSString *homePath =
NSHomeDirectory(); 
//NSHomeDirectory 沙盒的根目录
   
NSLog(@"homePath = %@",homePath);   
//  "/"

    
   
NSString *tempPath =
NSTemporaryDirectory();
   
NSLog(@"tempPath = %@",tempPath);

    

    NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask, YES);

    

    
   
NSString *path = [paths
lastObject];

    ///Users/apple/Library/Developer/CoreSimulator/Devices/0B364173-7C28-4376-84F4-671126E16FAD/data/Containers/Data/Application/41568158-8808-49C5-A41D-6432A1F74D3B/Library/aaa/1.txt

    

    

    //stringByAppendingPathComponent
给我们增加子路径

    path =  [path stringByAppendingPathComponent:@"aaa/1.txt"];

    //Library
下创建一个文件夹 ,文件夹名是aaa/1.txt

    
   
NSLog(@"path = %@",path);

    

//    NSFileManager *fm = [NSFileManager defaultManager];

//    //在沙盒下Library中先创建目录

//    [fm createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];

    
   
NSString *str = @"abc";

    BOOL isYes = [str
writeToFile:path atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
   
NSLog(@"%d",isYes);

——————————————————————————————

——————————————————————————————
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: