zoukankan      html  css  js  c++  java
  • iOS 中的 nil、Nil、NULL、NSNull 僵尸对象和野指针

     一、nil 、NSNull、Nil、NULL 区别

    1、nil
    我们给对象赋值时一般会使用object = nil,表示我想把这个对象释放掉;
    或者对象由于某种原因,经过多次release,于是对象引用计数器为0了,系统将这块内存释放掉,这个时候这个对象为nil,我称它为“空对象”。(注意:我这里强调的是“空对象”,下面我会拿它和“值为空的对象”作对比!!!)
    所以对于这种空对象,所有关于retain的操作都会引起程序崩溃,例如字典添加键值或数组添加新原素等,具体可参考如下代码:


     

    2、NSNull
    NSNull和nil的区别在于,nil是一个空对象,已经完全从内存中消失了,而如果我们想表达“我们需要有这样一个容器,但这个容器里什么也没有”的观念时,我们就用到NSNull,我称它为“值为空的对象”。如果你查阅开发文档你会发现NSNull这个类是继承NSObject,并且只有一个“+ (NSNull *) null;”类方法。这就说明NSNull对象拥有一个有效的内存地址,所以在程序中对它的任何引用都是不会导致程序崩溃的。参考代码如下:


     

    3、Nil
    nil和Nil在使用上是没有严格限定的,也就是说凡是使用nil的地方都可以用Nil来代替,反之亦然。只不过从编程人员的规约中我们约定俗成地将nil表示一个空对象,Nil表示一个空类。参考代码如下:


     

    4、NULL
    我们知道Object-C来源于C、支持于C,当然也有别于C。而NULL就是典型C语言的语法,它表示一个空指针,参考代码如下:
    int *ponit = NULL;

     二、野指针,僵尸指针、僵尸对象

    野指针

    先来介绍一下野指针,C/C++中对野指针的定义为:野指针就是指向垃圾内存的指针,这个指针地址不是NULL。如果给一个指针赋值为NULL,那么该指针就是一个空指针,可以用if语句判读。但是对于野指针不能用if语句判断。

    野指针产生的原因

    1)指针变量没有被初始化。任何指针在创建时都不会自动赋值为NULL,那么如果不初始化,它指向的内存地址是不确定的。所以在创建时,应该进行初始化。

    char *ptr = NULL;
    char *str = (char*)malloc(32);

    2)指针被释放(free或malloc)之后,没有设置为NULL,误以为是个合法指针。

    复制代码
    void function( void )  
    {  
        char* str = new char[100];  
        delete[] str;  
        // Do something  
        strcpy( str, "Dangerous!!" );  
    } 
    复制代码

    3)指针操作超出了变量的作用范围。

    复制代码
    class A 
    {    
        public:
            void Func(void){ cout << “Func of class A” << endl; }
    };
    void Test(void)
    {
        A *p;
        {
            A a;
            p = &a;    // 注意 a 的生命期
        }
        p->Func();        // p是“野指针”
    }
    复制代码

    函数 Test 在执行语句 p->Func() 时 ,对象 a 已经消失,而 p 是指向 a 的,所以 p 就成了 “野指针”。

    僵尸指针

    “僵尸指针”就是野指针的一种情况,即该指针指向的对象已经被释放,但是却没有对当前指针赋值为nil。

    僵尸对象

    简单的来说,僵尸对象是已经被释放的对象。如果在程序中再度使用该对象,一般会出现如下报错:

    unrecognized selector sent to instance

    今天就遇到了这样的一个报错:

    解决方案

    可以在Xcode的scheme页面中设置NSZombieEnabled环境变量。点击Product——>Edit Scheme打开该页面,然后勾选Enable Zombie Objects 复选框。如下图所示:

    NSZombieEnabled变量用来调试与内存有关的问题,跟踪对象的释放过程。启用了NSZombieEnabled,它会用一个僵尸来替换默认的dealloc实现,也就是在引用计数降到0时,该僵尸实现会将该对象转换成僵尸对象。僵尸对象的作用是在你向它发送消息时,它会显示一段日志并自动跳入调试器。启用NSZombie而不是让应用直接崩溃掉时,一个错误的内存访问就会变成一条无法识别的消息发送给僵尸对象。僵尸对象会显示接受到得信息,然后跳入调试器,这样你就可以查看到底是哪里出了问题。

    为什么不默认开启僵尸对象检测呢?

    因为一旦开启,每次通过指针访问对象的时候,都会去检查指针指向的对象是否为僵尸对象。所以会影响程序的执行效率,建议关闭。

    参考:
    http://www.jianshu.com/p/2b44e1c346e7

    http://www.cnblogs.com/tgycoder/p/5661431.html

  • 相关阅读:
    wait与sleep区别?
    oracle死锁查询
    atomic 原子操作的类
    买票问题
    0001.第一个多线程demo--分批处理数据
    01: JavaScript实例
    01: 运维工作梳理
    04: 使用BeautifulSoup封装的xss过滤模块
    04: 打开tornado源码剖析处理过程
    03: 自定义异步非阻塞tornado框架
  • 原文地址:https://www.cnblogs.com/saytome/p/7645161.html
Copyright © 2011-2022 走看看