C中的野指针,C++中的迷途指针(失控指针或悬浮指针)都是不为NULL的指针,也不是指向常量的指针,而是指向“垃圾”内存的指针。“垃圾”的意思是未知区域、未知内存。
例如,当我们定义一个指针的时候:
void main() { int *p; }
p的值为0xcccccccc。也就是说,任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱 指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。这也就是为什么我们在指针一开始创建时就给它赋一个值总是没有错的。
指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例:
int main() { int *pInt = new int; *pInt=10; cout<<pInt<<endl; cout<<"*pInt: "<<*pInt<<endl; delete pInt; //pInt为迷途指针! int *pLong = new int; cout<<pInt<<endl; cout<<pLong<<endl; *pLong=90000; cout<<"*pLong: "<<*pLong<<endl; *pInt=20; //再次使用pInt! cout<<"*pInt: "<<*pInt<<endl; cout<<"*pLong: "<<*pLong<<endl; delete pLong; return 0; }
程序直接运行的输出结果为:
我们发现程序出现了错误,原因是当我们用delete删掉pInt时,程序只是删除了pInt所指向的那段内存地址,该变量所指向的地址值并没有变,如下:
pInt在删除之前的值为0x00382fe0,删除后的值依然是0x00382fe0,并且和pLong指向相同的内存地址,因此,某一个值的改变势必也会引起另一个值的改变。避免的方式是在delete pInt的后面加上pInt = NULL;
但是单步调试的时候结构却是正确的。不懂!
另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。【维基百科】给出了下面的一段代码:
//C++迷途指针 #include <iostream> using namespace std; int *p = 0; int * func ( void ) { int num = 1234; /* ... */ return # } int* func2(void) { int k = 12; cout<<"调用函数2"<<endl; p = &k; return p;; } int main() { cout<<*func()<<endl; func2(); cout<<*func()<<endl; }
在调用func,尝试从该指针中读取num的值,仍然能够返回正确的值(1234),但是任何的函数调用会覆盖原来的栈为num分配的空间。这时,再从该指针读取num的值就不正确了。如果要使一个指向num的指针都返回正确的num值,则需要将该变量声明为static。但是这段代码没有搞懂。
第二个错误:比如在类的定义时的构造函数和析构函数,如果在构造函数中动态开辟(new),在析构函数中要释放,然而我们一般都delete释放内存后就结束了,殊不知,指向先前内存的指针就成了野指针(迷途指针),稍有不慎,就会出错,当你向未知区域赋值时,运气好的话会是程序运行错误,要是运气不佳,很可能引起系统崩溃!