野指针
定义
野指针是指指向一个已删除的对象或未申请访问受限内存区域的指针。
成因
1、指针变量未初始化
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。如果没有初始化,编译器会报错“ ‘point’ may be uninitializedin the function ”。
2、对象已删除,但指针未置空
例如:
int *p = (int *)malloc(4);
free(p);
这里,虽然通过free释放了堆上的内存空间,但指针仍然留在栈中,形成了野指针,正确的做法是:
int *p = (int *)malloc(4);
free(p);
p = NULL;
或引用相关宏定义或函数来释放
#define xfree(x) free(x); x = NULL;
或者
// 在 C++ 中应使用 nullptr 指代空指针
// 一些平台上的 C/C++ 已经预先添加了 xfree 拓展,如 GNU 的
libiberty
xfree(p);
// 用函数实现,例如 GitHub 上的 AOSC-Dev/Anthon-Starter #9:
static inline void *Xfree(void *ptr) {
free(ptr);
#ifdef __cplusplus
return nullptr;
#else
return NULL;
#endif
}
q=Xfree(q);
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 就成了“野指针” 。
野指针的危害
1、指向不可访问的地址
危害:触发段错误。
2、指向一个可用的,但是没有明确意义的空间
危害:程序可以正确运行,但通常这种情况下,我们就会认为我们的程序是正确的没有问题的,然而事实上就是有问题存在,所以这样就掩盖了我们程序上的错误。
3、指向一个可用的,而且正在被使用的空间
危害:如果我们对这样一个指针进行解引用,对其所指向的空间内容进行了修改,但是实际上这块空间正在被使用,那么这个时候变量的内容突然被改变,当然就会对程序的运行产生影响,因为我们所使用的变量已经不是我们所想要使用的那个值了。通常这样的程序都会崩溃,或者数据被损坏。
如何避免
在养成这些习惯的情况下,野指针的危害是可以降低的:
1、初始化时置 NULL
指针变量一定要初始化为NULL,因为任何指针变量(除了static修饰的指针变量)刚被创建时不会自动成为NULL指针,它的缺省值是随机的。
2、释放时置NULL
当指针p指向的内存空间释放时,没有设置指针p的值为NULL。delete和free只是把内存空间释放了,但是并没有将指针p的值赋为NULL。通常判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。