什么是野指针

转载 2008年10月03日 09:55:00
野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:

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

二、 指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是 delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例:

char *p = (char *) malloc(100);

strcpy(p, “hello”);

free(p); // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL) // 没有起到防错作用

strcpy(p, “world”); // 出错

另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。

 

 

 

野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。首先请诸位看以下一段“危险”的C++代码:

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


之 所以说其危险,是因为这是一段完全合乎语法的代码,编译的时候完美得一点错误也不会有,然而当运行到strcpy一句的时候,问题就会出现,因为在这之 前,str的空间已经被delete掉了,所以strcpy当然不会成功。对于这种类似的情况,在林锐博士的书中有过介绍,称其为“野指针”。

那么,诸位有没有见过安全的“野指针”呢?下面请看我的一段C++程序,灵感来自CSDN上的一次讨论。在此,我只需要C++的“类”,C++的其余一概不需要,因此我没有使用任何的C++标准库,连输出都是用printf完成的。

#include <stdio.h>

class CTestClass
{
public:
CTestClass( void );
int m_nInteger;
void Function( void );
};

CTestClass::CTestClass( void )
{
m_nInteger = 0;
}

void CTestClass::Function( void )
{
printf( "This is a test function./n" );
}

void main( void )
{
CTestClass* p = new CTestClass;
delete p;
p->Function();
}


OK,程序到此为止,诸位可以编译运行一下看看结果如何。你也许会惊异地发现:没有任何的出错信息,屏幕上竟然乖乖地出现了这么一行字符串:

This is a test function.

奇怪吗?不要急,还有更奇怪的呢,你可以把主函数中加上一句更不可理喻的:

((CTestClass*)NULL)->Function();


这仍然没有问题!!

我这还有呢,哈哈。现在你在主函数中这么写,倘说上一句不可理喻,那么以下可以叫做无法无天了:

int i = 888;
CTestClass* p2 = (CTestClass*)&i;
p2->Function();


你看到了什么?是的,“This is a test function.”如约而至,没有任何的错误。

你也许要问为什么,但是在我解答你之前,请你在主函数中加入如下代码:

printf( "%d, %d", sizeof( CTestClass ), sizeof( int ) );


这 时你就会看到真相了:输出结果是——得到的两个十进制数相等。对,由sizeof得到的CTestClass的大小其实就是它的成员m_nInteger 的大小。亦即是说,对于CTestClass的一个实例化的对象(设为a)而言,只有a.m_nInteger是属于a这个对象的,而 a.Function()却是属于CTestClass这个类的。所以以上看似危险的操作其实都是可行且无误的。

现在你明白为什么我的“野指针”是安全的了,那么以下我所列出的,就是在什么情况下,我的“野指针”不安全:

在成员函数Function中对成员变量m_nInteger进行操作;
将成员函数Function声明为虚函数(virtual)。
以上的两种情况,目的就是强迫野指针使用属于自己的东西导致不安全,比如第一种情况中操作本身的m_nInteger,第二种情况中变为虚函数的Function成为了属于对象的函数(这一点可以从sizeof看出来)。

其 实,安全的野指针在实际的程序设计中是几乎毫无用处的。我写这一篇文章,意图并不是像孔乙己一样去琢磨回字有几种写法,而是想通过这个小例子向诸位写明白 C++的对象实例化本质,希望大家不但要明白what和how,更要明白why。李马二零零三年二月二十日作于自宅。


关于成员函数CTestClass::Function的补充说明



这个函数是一个普通的成员函数,它在编译器的处理下,会成为类似如下的代码:

void Function( const CTestClass * this ) // ①
{
printf("This is a test function./n");
}


那么p->Function();一句将被编译器解释为:

Function( p );


这 就是说,普通的成员函数必须经由一个对象来调用(经由this指针激活②)。那么由上例的delete之后,p指针将会指向一个无效的地址,然而p本身是 一个有效的变量,因此编译能够通过。并且在编译通过之后,由于CTestClass::Function的函数体内并未对这个传入的this指针进行任何 的操作,所以在这里,“野指针”便成了一个看似安全的东西。

然而若这样改写CTestClass::Function:

void CTestClass::Function( void )
{
m_nInteger = 0;
}


那么它将会被编译器解释为:

void Function( const CTestClass * this )
{
this->m_nInteger = 0;
}


你看到了,在p->Function();的时候,系统将会尝试在传入的这个无效地址中寻找m_nInteger成员并将其赋值为0,剩下的我不用说了——非法操作出现了。

至于virtual虚函数,如果在类定义之中将CTestClass声明为虚函数:

class CTestClass
{
public:
// ...
virtual void Function( void );
};


那 么C++在构建CTestClass类的对象模型时,将会为之分配一个虚函数表vptr(可以从sizeof看出来)。vptr是一个指针,它指向一个函 数指针的数组,数组中的成员即是在CTestClass中声明的所有虚函数。在调用虚函数的时候,必须经由这个vptr,这也就是为什么虚函数较之普通成 员函数要消耗一些成本的缘故。以本例而言,p->Function();一句将被编译器解释为:

(*p->vptr[1])( p ); // 调用vptr表中索引号为1的函数(即Function)③


上面的代码已经说明了,如果p指向一个无效的地址,那么必然会有非法操作。

备注:

①关于函数的命名,我采用了原名而没有变化。事实上编译器为了避免函数重载造成的重名情况,会对函数的名字进行处理,使之成为独一无二的名称。
②将成员函数声明为static,可以使成员函数不经由this指针便可调用。
③vptr表中,索引号0为类的type_info。

什么是野指针和内存泄漏?如何避免野指针

内存泄漏:①访问已经释放的内存     ②访问没有权限的内存 野指针:指向内存被释放的内存或者没有访问权限的内存的指针。 “野指针”的成因主要有3种: (1)指针变量没有被初始化。任何指针变...
  • qq_35212671
  • qq_35212671
  • 2016年07月15日 20:35
  • 1378

什么是野指针?应该如何避免?

什么是野指针?应该如何避免? 野指针:指向不确定地址的指针变量。(即没有初始化)...
  • xieyihua1994
  • xieyihua1994
  • 2016年05月16日 22:38
  • 3528

野指针和空指针

Person *p = [[Person alloc] init]; /* 只要一个对象被释放了,我们就称这个对象为“僵尸对象” 当一个指针指向一个僵尸对象,我们...
  • github_26672553
  • github_26672553
  • 2016年01月10日 20:44
  • 550

谈谈你对野指针的理解?

谈谈你对野指针的理解?   野指针不是NULL指针,是指向“垃圾”内存的指针。即它是随机指向的,系统自动对其初始化。   野指针会造成什么样的后果呢? 最大的问题:它会导致内存泄漏。   ...
  • Turchar
  • Turchar
  • 2016年04月25日 09:56
  • 687

什么是野指针?迷途指针!悬空指针!

一、迷途指针 迷途指针与野指针指的是不指向任何合法的对象的指针。 当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称迷途指针。若操作...
  • yusiguyuan
  • yusiguyuan
  • 2014年02月28日 08:20
  • 3329

野指针与僵尸对象

野指针.C语言: 当我们声明1个指针变量,没有为这个指针变量赋初始值.这个指针变量的值是1个垃圾指 指向1块随机的内存空间。 OC语言: 指针指向的对象已经被回收掉了.这个指针就叫做野指针.僵尸对象....
  • yi_zz32
  • yi_zz32
  • 2015年09月21日 23:58
  • 8948

c/c++:内存泄露和野指针的概念

内存泄漏  用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏。    注意:内存泄漏是指堆内存的泄漏。  简...
  • dangercheng
  • dangercheng
  • 2013年10月11日 15:47
  • 4697

面试-野指针,悬挂指针

首先说明一点: 指向非法的内存地址(垃圾内存的地址),那么这个指针就是悬挂指针,也叫野指针,意为无法正常使用的指针。 野指针(悬挂指针): 野指针是指向不可用内存区域的指针(非法内存,垃圾内...
  • msdnwolaile
  • msdnwolaile
  • 2016年03月27日 11:27
  • 1511

悬挂指针与野指针

悬挂指针/Dangling Pointers/迷途指针/悬垂指针 野指针/Wild Pointers
  • chunyexiyu
  • chunyexiyu
  • 2016年09月29日 12:38
  • 495

c++三种野指针

野指针,也就是指向不可用内存区域的指针。如果对野指针进行操作,将会使程序发生不可预知的错误,甚至可能直接引起崩溃。         野指针不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用...
  • a2796749
  • a2796749
  • 2015年07月15日 18:49
  • 1579
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:什么是野指针
举报原因:
原因补充:

(最多只允许输入30个字)