野指针问题
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 = # // ----> 合法方法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; }