野指针 悬垂指针 迷途指针
一、悬垂指针
当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称悬垂指针(也叫迷途指针)。若操作系统将这部分已经释放的内存重新分配给另外一个进程,而原来的程序重新引用现在的迷途指针,则将产生无法预料的后果。因为此时迷途指针所指向的内存现在包含的已经完全 是不同的数据。通常来说,若原来的程序继续往迷途指针所指向的内存地址写入数据,这些和原来程序不相关的数据将被损坏,进而导致不可预料的程序错误。这种类型的程序错误,不容易找到问题的原因,通常会导致段错误(Linux系统中)和一般保护错误(Windows系统中)。如果操作系统的内存分配器将已经被覆盖的数据区域再分配,就可能会影响系统的稳定性。
某些编程语言允许未初始化的指针的存在,而这类指针即为野指针。野指针所导致的错误和迷途指针非常相似,但野指针的问题更容易被发现。
二、悬垂指针的成因
在许多编程语言中(比如C),显示地从内存中删除一个对象或者返回时通过销毁栈帧,并不会改变相关的指针的值。该指针仍旧指向内存中相同的位置,即使引用已经被删除,现在可能已经挪作他用。
一个简单的例子:
{
char *dp = NULL;
/* ... */
{
char c;
dp = &c;
} /* c falls out of scope *//* dp is now a dangling pointer */
}
上述问题的解决方法是在该部分程序退出之前立即给CP赋0值(NULL)。另一个办法是保证CP在没有初始化之前,将不再被使用。
迷途指针经常出现在混杂使用malloc() 和 free() 库调用: 当指针指向的内存释放了,这时该指针就是迷途的。和前面的例子一样,一个避免这个错误的方法是在释放它的引用后将该指针的值重置为NULL,如下所示:
#include <stdlib.h>
{
char *cp =malloc ( A_CONST );
/* ... */
free ( cp); /* cp now becomes a danglingpointer */
cp = NULL; /* cp is no longer dangling */
/* ... */
}
有个常见的错误是当返回一个基于栈分配的局部变量的地址时,一旦调用的函数返回,分配给这些变量的空间将被回收,此时它们拥有的是"垃圾值"。
int * func ( void )
{
int num = 1234;
/* ... */
return #
}
在调用func之后一段时间,尝试从该指针中读取num的值,可能仍然能够返回正确的值(1234),但是任何接下来的函数调用会覆盖原来的栈为num分配的空间。这时,再从该指针读取num的值就不正确了。如果要使一个指向num的指针都返回正确的num值,则需要将该变量声明为static。
三、野指针的产生
野指针指的是还没有初始化的指针。严格地说,编程语言中每个指针在初始化前都是野指针。
一般于未初始化时便使用指针就会产生问题。大多数的编译器都能检测到这一问题并警告用户。
int f(int i)
{
char* cp; //cp is a wild pointer
static char*scp; //scp is not a wild pointer: staticvariables are initialized to 0
//at start and retain their values from the last call afterwards.
//Using this feature may be considered bad style if not commented
}
cp是一个野指针,scp不是野指针。静态变量一开始被初始化为0,从最后一次调用后保持着它们的值。如果没有注释,使用这个特性也许被视为不良风格。
四、避免悬垂指针的产生
在 C/C++ 中,一种最简单的技术是实现一个 free()(或类似的)替代版本或者 delete 析构器来保证指针的重置。然后,这个技术不会清除其他指针变量,它们含有该指针的副本。
/* Alternative version for free*/
void safefree(void **pp)
{
if(pp!=NULL){ /* safe check*/
free(*pp); /*deallocate chunk,note that free(NULL) is valid*/
*pp=NULL; /* reset original pointer*/
}
int function(int i)
{
char *p=NULL,*p2;
p=(char*)malloc(1000); /*get a chunk*/
p2=p; /*copy the pointer*/
/*use the chunk here*/
safefree(&p); /*safety freeing;does not effect p2 variable*/
safefree(&p); /*this second call won't fail*/
char c=*p2;/*p2 is still a dangling pointer ,so this is undefined behavior*/
这些用法可以通过 #define 指令来构造有用的宏指令,创建像元语言的东西来掩饰或者被嵌入到一个工具库中。但凡使用这个技术的程序员在会用到 free()的地方应该使用安全版本;不这么做会再次导致这些问题。另外,这个解决方案局限于单个程序或工程的作用域中,并且应该正确地写入文档。
在更多结构化的解决方案中,一种流行的避免悬垂指针的技术是使用智能指针。一个智能指针通常使用引用技术来收回对象。还有些技术包括 tombstones 方法和 locks-and-keys 方法。
另一个方法是使用 Boehm 垃圾收集器,一种保守的垃圾收集器,取代C和C++中的标准内存分配函数。此法通过禁止内存释放函数来完全消除悬垂指针引发的错误,通过收集垃圾来回收对象。
像Java语言,悬垂指针这样的错误是不会发生的,因为Java中没有明确地重新分配内存的机制。而且垃圾回收器只会在对象的引用数为0时重新分配内存。
五、悬垂指针的检测
为了能发现迷途指针,一种普遍的编程技术——一旦指针指向的内存空间被释放,就立即把该指针置为空指针或者为一个非法的地址。
当空指针被重新引用时,此时程序将会立即停止,这将避免数据损坏或者某些无法预料的后果。这将使接下来的编程过程产生的错误变得容易发现和解决了。
这种技术在该指针有多个复制时就无法起到应有的作用了。
转载于:https://blog.51cto.com/8599721/1373537
野指针 悬垂指针 迷途指针相关推荐
- C++迷途指针(dangling pointer)与野指针
1.野指针是指没有初始化的指针,如下: #include<stdio.h> int main(int argc,char * argv[]){int *p;return (*p&0 ...
- 迷途指针,从百度百科上摘抄的,语言很幽默
迷途(stray)指针,也被称为野(wild)指针或悬浮(dangling)指针,是指将delete 用于指针(从而释放它指向的内存),但没有将它设置为空时引发.如果随后你在没有重新赋值的情况下使用该 ...
- C++阶段01笔记07【指针(基本概念、变量定义和使用、内存空间、空指针和野指针、const修饰指针、指针和数组、指针和函数)】
C++| 匠心之作 从0到1入门学编程[视频+课件+笔记+源码] 目录 7 指针 7.1 指针的基本概念 7.2 指针变量的定义和使用 示例 7.3 指针所占内存空间 示例 7.4 空指针和野指针 示 ...
- 复制构造函数的用法及出现迷途指针问题
复制构造函数利用下面这行语句来复制一个对象: A (A &a) 从上面这句话可以看出,所有的复制构造函数均只有一个参数,及对同一个类的对象的引用 比如说我们有一个类A,定义如下: ? 1 ...
- 指针、野指针、指针常量、常量指针
指针 概念 指针是什么? 在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值.由于通过地址能找到所需的变量单元,可以说,地址指向该变量 ...
- C++面试题-指针-指针数组与数组指针
C++面试题-指针-指针数组与数组指针 问:int (*p)[n]与int *p[n]的区别? 答: int (*p)[n]是数组指针,指向某n个元素所组成的整块的数组,返回值是整型指针类型的. in ...
- C++ 笔记(14)— 指针(指针声明、取地址、取值、new/delete、NULL指针、指针运算、指针数组、数组指针、指针传递给函数、从函数返回指针)
1. 声明指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指 针存储其他变量地址之前,对其进行声明. 指针变量声明的一般形式为: type * ...
- 弄清指针-如何深入了解指针
弄懂这些指针基础知识,再遇C指针咱就不慌了 一.前言 二.变量与指针的本质 三.指针的几个相关概念 四.指向不同数据类型的指针 五.总结 一.前言 如果问C语言中最重要.威力最大的概念是什么,答案必将 ...
- 指针数组概念 和 函数指针数组实战 和指针函数的概念和实战
1.指针数组概念 int (*p)[4]; 是一个数组指针 ,强调的是指针,这是指针指向的是某个数组 (*p)这个指针含有四个元素的一维数组 指针数组呢? 强调的是数组 我们可以定义一个数组,数组里面 ...
最新文章
- swift_018(Swift 的结构体)
- 2.	html表单提交servlet出现的乱码问题的解决?
- AI 补代码神器诞生,百度网盘克星诞生,Google 取消中国搜索引擎项目! | 开发者周刊...
- oracle存储过程(带参数的存储过程)
- 微信小程序之WeUI组件库的使用
- 如何删除双系统中的Linux系统
- 鞍点【C语言】完整可用
- 多多自走棋服务器不稳定,多多自走棋突然宣布停服,数据将全部转移到腾讯服务器中...
- 金蝶K3开发-基础资料插件开发
- 数字证书及公钥、私钥
- Lucas定理相关证明
- 轨道六根数的含义汇总
- Android3D抽方块源码,block puzzle jewel 方块拼图消除游戏安卓源码
- Spring Boot Admin在线查看spring boot后台日志
- 东南大学计算机复试被刷概率,二战东大复试被刷恼羞成怒东大有内幕,今为黑东大之行为而后悔不已...
- c语言判断真假,C语言中的真假值
- 解读凯文·凯利《失控》
- [附源码]Java计算机毕业设计SSM城市智能公交系统
- Pytorch:手把手教你搭建简单的卷积神经网络(CNN),实现MNIST数据集分类任务
- Citavi入门使用教程
热门文章
- HDU 3394 Railway(点双连通分量)
- utuntu 视频 无声
- OenLayers 事件注册
- 样式定义Android界面样式
- 手把手教你写个ORM(一)
- layui fixbar 返回顶部_卖在顶部(四)
- 带瀑布流的电钢琴_《EduOffice数字音乐电钢琴互动教室教学系统》系统特色之六:创...
- linux什么命令查设备型号,在Linux命令行中查看系统硬件制造商、型号与序列号的六种方法...
- 计算机小白学生物信息的难度,基因表达数据分析,对于还是分子生物学小白的我来说太难了。。。...
- Java ArrayList到数组