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

  • 相关阅读:
    215. Kth Largest Element in an Array
    214. Shortest Palindrome
    213. House Robber II
    212. Word Search II
    210 Course ScheduleII
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    206. Reverse Linked List
    sql 开发经验
  • 原文地址:https://www.cnblogs.com/saytome/p/7645161.html
Copyright © 2011-2022 走看看