内存管理

来源:互联网 发布:剑网三萝莉脸型数据图 编辑:程序博客网 时间:2024/04/26 14:14

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

1-对象所有权:


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


    2-引用计数


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


    3-引用计数器


      记录使用者的个数的变量

      变量类型  unsigned  long

      方法  retainCount

      打印引用计数器的值   %lu



    4-引用计数器的作用


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

      如果为0   要回收

      如果>0    不要回收


    5-对引用计数器的操作


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

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


      向对象 发送 release 消息

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



    6-对象回收注意:


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



    MRC - 手动内存管理

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





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

//创建一个实例对象

       Person *p = [Personnew];

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

    

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

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

        //对象创建完成后,默认的有一个所有者,就是他自己

       NSUInteger n = [p retainCount];

        [pretain]; // 让引用计数期的值+1

        

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

        

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

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

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

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

        

        [prelease];         //0

       //

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

        [prelease];




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

 

   

   只要对象的引用计数不为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) retainrelease的个数不匹配问题

 

    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(默认)   - 生成getset方法

      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 = [NSStringstringWithString:@"def"];

       NSString *str3 = [[NSStringalloc] initWithString:@"abc"];

        //0x100602420

       //堆区

       NSString *str4 = [NSStringstringWithFormat:@"aaa"];

       NSString *str5 = [NSStringstringWithFormat:@"aaa"];

       NSString *str6 = [[NSStringalloc] initWithFormat:@"bbbb"];

        

       NSString *str7 = [[NSStringalloc] init];

        [str7release];

        

        

        //此时因为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 = [Carnew];


    [bigBenrun];


    [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 = [strwriteToFile:path atomically:YESencoding:NSUTF8StringEncodingerror:nil];

   NSLog(@"%d",isYes);



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



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




0 0
原创粉丝点击