• 关于OC的内存管理-01


    1.什么是内存管理?

    大家都知道手机的内存是有限的,app应用的内存也应该是受限制的,随着app应用的使用会导致内存的占用率增大。当内存占用率达到一种程度时。系统会发出内存警告。这时我们须要把一些不用的对象和变量所占用的内存释放掉,也就是说我们须要手动对内存进行管理。

    而我们管理的范围:不论什么继承了NSObject 的对象,对于基本数据类型(比方float、int 、char、struct、enum等)则是无效的。


    2.怎样进行内存管理

    1)每一个OC对象本身就有一个占用4个字节内存的计数器,它存储的是一个整数。表示“当前对象被引用的次数”。当对象一被建立的时候(比如alloc、new、copy)就默觉得1。而计数器的作用就是,当对象的计数器为0时,当前对象就会被系统回收,假设计数器不为0,程序的整个运行过程中,当前对象的内存就一直不回被回收





    2)引用计数器的三种操作

    (1)retain(给对象发送消息一条retain消息)   计数器+1,有返回值,返回的是对象本身

    (2)release (给对象发送消息一条release消息)计数器-1。无返回值。

    (3)retainCount (给对象发送消息一条retainCount消息)获取当前对象的引用计数器值

    3.当对象销毁时系统会自己主动调用dealloc方法,dealloc方法就像临终遗言一样,所以我们一般重写dealloc方法

    而且此方法中,一定要有[super dealloc] ,且一定放在最后面。

    3.如果我们有一个Person 类

    #import <Foundation/Foundation.h >

    @interface Person : NSObject

    {

    {

    int _age ;

    }

    -(void)setAge:(int)age;

    -(int)age;

    }


    #import"Person.h"

    @implementation Person

    {

    -(void)setAge:(int)age{


    _age = age ;

    }



    -(int)age{

    return _age;

    }

    -(void)dealloc{

    NSLog(@"Person 对象被回收");

    [super dealloc]。

    }


    (1)第一种情况

    int main(){

    //当我们一调用alloc时,对象计数器就默觉得1。所以一有alloc ,我们须在后面加上[对象名 release]

    //p-1(当前计数器为1)

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

    //p-2(当前计数器为2)

    [p retain];

    //release表示计数器减1,此时p-1

    [p  release];

    //p-0,这时系统会回收对象p ,运行对象p的dealloc方法

    [p  release];

    return 0;

    }


    (2)另外一种情况


    int main(){

    //当我们一调用alloc时,对象计数器就默觉得1。

    所以一有alloc ,我们须在后面加上[对象名 release]

    //p-1(当前计数器为1)

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

    //p-2(当前计数器为2)

    [p retain];

    //release表示计数器减1,此时p-1

    [p  release];

    //p-0,这时系统会回收对象p 。运行对象p的dealloc方法

    [p  release]。


    //特别。此时系统已把对象p回收,假设我们在这里再多次运行[p release]的话

    //会訪问僵尸对象(已被系统回收的对象,一块不可用的内存)

    //而p这时则叫野指针(指向僵尸对象的指针),会造成坏的訪问即EXC_BAD_ACCESS

    return 0;

    }


    如图:



    (3)第三种情况


    int main(){

    //当我们一调用alloc时,对象计数器就默觉得1。所以一有alloc ,我们须在后面加上[对象名 release]

    //p-1(当前计数器为1)

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

    //p-2(当前计数器为2)

    [p retain];

    //release表示计数器减1,此时p-1

    [p  release];

    //p-0。这时系统会回收对象p ,运行对象p的dealloc方法

    //运行此句的话。假设不打开Enable Zoombie Object 则不会报错

    //假设打开的话。则会出现这种提示错误

    //message send to deallocated instance

    //意思是给已经回收的实例发送消息

    p.age = 10;

    return 0;

    }

    如图:

    (4)第四种情况;

    int main(){

    //当我们一调用alloc时,对象计数器就默觉得1。所以一有alloc ,我们须在后面加上[对象名 release]

    //p-1(当前计数器为1)

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

    //p-2(当前计数器为2)

    [p retain];

    //release表示计数器减1,此时p-1

    [p  release];

    [p  release];

    //结合第三种情况。我们就会这样想,这时计数器本来是0,我们能够运行retain。计数器+1

    //我们不就能够成功运行p.age = 10;了吗 其实,回收的对象是不可能死而复生的。

    //运行的结果如上图。

    //message send to deallocated instance

    //意思是给已经回收的实例发送消息

    p.age = 10;

    return 0;

    }




  • 相关阅读:
    最详细的Vue Hello World应用开发步骤
    SAP Fiori + Vue = ?
    golang--连接redis数据库并进行增删查改
    golang--redis基本介绍
    golang--海量用户即时通讯系统
    (四十六)golang--网络编程(简易的聊天系统)
    动态规划--矿工挖矿
    (四十五)golang--反射
    动态规划--爬楼梯问题(入门)
    (四十四)golang--协程(goroutine)和管道(channel)相结合实例
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6853336.html
Copyright © 2020-2023  润新知