野指针问题

 

1. 定义:

  野指针是指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为NULL来避免,而只能通过养成良好的编程习惯来尽力减少,对野指针进行操作容易造成程序错误。

 

2. 形成原因:

(1)指针变量未初始化

  任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

(2)指针释放之后未置空

  有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字,它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。

(3)指针操作超越变量作用域

  不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放,示例程序如下:

class A
{
public:
    void Func(void)
    {
        cout << “Func of class A” << endl;
    }
};
class B
{
public:
    A *p;
    void Test(void)
    {
        A a;
        p = &a;                 // 注意 a 的生命期, 只在这个函数Test中有效, 而不是整个class B
    }
    void Test1()
    {
        p->Func();              // p 成为"野指针"
    }
};

函数 Test1 在执行语句 p->Func()时,p 的值还是 a 的地址,但对象 a 的内容已经被清除,所以 p 就成了“野指针” 。

 

3. 测试代码:

#include <stdio.h>
#include <iostream>
using namespace std;

int main()
{
    int *ppp = NULL;                                  //       ----> 合法方法3

    int num = 10;
    int *pp;
    pp = &num;                                        //       ----> 合法方法2

    int *p = new int;                                 //       ----> 合法方法1
    *p = 10;

    /*-------------------------------- 以 下 错 误 写 法 --------------------------------*/
    delete p;
    printf("%d\n", (p==NULL) ? 1 : 0);                // 0     ----> p指针释放后未置空
    printf("%d\n", *p);                               // ?     ----> 未阻止对到账内存访问
    *p = 20;                                          //       ----> 未阻止对到账内存访问
    printf("%d\n", *p);                               // 20    ----> 未阻止对到账内存访问

    /*-------------------------------- 以 下 正 确 写 法 --------------------------------*/
    delete p;
    p = NULL;
    printf("%d\n", (p==NULL) ? 1 : 0);                // 1     ----> p指针释放后已置空
    if(p!=NULL)                                       //       ----> 不加判断三条语句都崩溃
    {
        printf("%d\n", *p);                           //       ----> 阻止了对到账内存的访问
        *p = 20;                                      //       ----> 阻止了对到账内存的访问
        printf("%d\n", *p);                           //       ----> 阻止了对到账内存的访问
    }
    return 0;
}

posted on 2015-08-16 10:59  huashunli  阅读(308)  评论(0编辑  收藏  举报

导航