C++中的悬挂指针和野指针
悬挂指针(Dangling Pointer), 指的是一个指针它指向已经释放的内存或者无效的内存。当指针指向的内存被释放,这个指针仍然保留着指向之前内存地址的数值,但该地址中的数据已经无效或者被其他数据覆盖
比如一个指针 *Ptr, 它最初指向了一块内存,现在这块内存被释放了,或者这块内存被释放后重新分配给别人,里面是其他的内容。但是这个时候 *Ptr指针依然指向这块内存,
这就会导致问题,它很有可能导致未定义的行为,比如访问无效的内存,程序崩溃或者产生不可预测的结果
我们来看一个关于悬挂指针的经典的例子:
#include <iostream>
int* CreateInt()
{
int testValue = 1;
int* ptr = &testValue; //指针存储函数内部的局部变量testValue的地址,所以*ptr是一个指向局部变量的指针
return ptr;
}
int main()
{
int* danglingPtr = CreateInt(); //这个时候产生了悬挂指针
//尝试访问悬挂指针指向的内存
std::cout << *danglingPtr << std::end1; //这条语句很有可能导致未定义的未知行为
return 0;
}
在上面这段代码中, int* danglingPtr = CreateInt(); => CreateInt()方法会返回一个int类型的指针,但是这个指针指向的是CreateInt()方法内部的局部变量testValue. 当我们用CreateInt()执行完这个方法并返回int类型的指针后,它里面的局部变量也就完成了生命周期,内存被释放了。但这个时候,悬挂指针*danglingPtr仍然指向了已经释放了的这块内存的地址。 所以,当我们试图去访问悬挂指针所指向的内存时,就很有可能会产生未定义的行为
为了避免悬挂指针的问题,我们在使用指针时应该注意以下几点:
1. 避免返回指向局部变量的指针
2. 在释放内存后,将指针置为nullPtr, 或者重新为这个指针分配其他有效的内存
3. 在使用指针前,始终都应该检查指针是否为有效指针
上面的例子,返回了指向函数的局部变量的指针,导致了悬挂指针的出现。这其实只是悬挂指针出现的一种情况,
接下来,我们来说说什么是野指针
野指针 =》 野指针是指尚未初始化的指针,也就是说声明了一个指针,但是还没有初始化。 此时它指向的地址是未知的,不确定的,随机的。 我们来看一个例子
#include<iostream> using namesapce std; int main() {
int* p1; //此时声明了,但没有初始化指针p1, 这个时候它就是野指针
cout << "*p1 = " << *p1 << end1; //指针*p1 未初始化就被使用
delete p1;
return 0; }
这样使用时,编译器会直接报错, 产生非法的内存访问
那么如何来避免这种野指针的情况呢,我们可以把指针初始化为NULL,如下
#include<iostream> using namespace std; int main() {
int* p1; //此时p1属于野指针
int* p2 = NULL; // 此时p2不属于野指针,因为给它赋予了初始值NULL
p1 = new int(10); //此时p1就不再是野指针了
p2 = new int(10);
cout << "*p1 = " << *p1 << end1;
cout << "*p2 = " << *p2 << end1;
delete p1;
delete p2;
return 0;
}