本文较为详尽的讲述了C语言的迷途指针,分析了其概念、原理与检测方法。分享给大家供大家参考。具体如下:
一般来说,在计算机编程领域中,迷途指针,或称悬空指针、野指针,指的是不指向任何合法的对象的指针。
当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称迷途指针。若操作系统将这部分已经释放的内存重新分配给另外一个进程,而原来的程序重新引用现在的迷途指针,则将产生无法预料的后果。因为此时迷途指针所指向的内存现在包含的已经完全是不同的数据。通常来说,若原来的程序继续往迷途指针所指向的内存地址写入数据,这些和原来程序不相关的数据将被损坏,进而导致不可预料的程序错误。这种类型的程序错误,不容易找到问题的原因,通常会导致段错误(Linux系统中)和一般保护错误(Windows系统中)。如果操作系统的内存分配器将已经被覆盖的数据区域再分配,就可能会影响系统的稳定性。
某些编程语言允许未初始化的指针的存在,而这类指针即为野指针。野指针所导致的错误和迷途指针非常相似,但野指针的问题更容易被发现。
迷途指针的成因
在很多编程语言中(如C语言)从内存中删除一个对象或者返回时删除栈帧后,并不会改变相关的指针的值。该指针仍然指向原来的内存地址,即使引用已经删除,现在也可能已经被其它进程使用了。
一个直接的例子,如下所示:
{ char *cp = NULL; /* ... */ { char c; cp = &c; } /* c falls out of scope */ /* cp is now a dangling pointer */ }
上述问题的解决方法是在该部分程序退出之前立即给CP赋0值(NULL)。另一个办法是保证CP在没有初始化之前,将不再被使用。
迷途指针经常出现在混杂使用malloc() 和 free() 库调用: 当指针指向的内存释放了,这时该指针就是迷途的。和前面的例子一样,一个避免这个错误的方法是在释放它的引用后将该指针的值重置为NULL,如下所示:
#include <stdlib.h> { char *cp = malloc ( A_CONST ); /* ... */ free ( cp ); /* cp 现在变成了一个悬空指针 */ cp = NULL; /* cp 现在不是悬空了 */ /* ... */ }
有个常见的错误是当返回一个基于栈分配的局部变量的地址时,一旦调用的函数返回,分配给这些变量的空间将被回收,此时它们拥有的是"垃圾值"。
int * func ( void ) { int num = 1234; /* ... */ return # }
在调用func之后一段时间,尝试从该指针中读取num的值,可能仍然能够返回正确的值(1234),但是任何接下来的函数调用会覆盖原来的栈为num分配的空间。这时,再从该指针读取num的值就不正确了。如果要使一个指向num的指针都返回正确的num值,则需要将该变量声明为static。
野指针的产生
野指针指的是还没有初始化的指针。严格地说,编程语言中每个指针在初始化前都是野指针。
一般于未初始化时便使用指针就会产生问题。大多数的编译器都能检测到这一问题并警告用户。
int f(int i) { char* cp; //cp 是野指针 static char* scp; //scp 不是野指针,静态变量自动初始化为0并保留它们的值 //使用这种特征可能被认为坏的编程风格 }
迷途指针导致的安全漏洞
如同缓存溢出错误,迷途指针/野指针这类错误经常会导致安全漏洞。 例如,如果一个指针用来调用一个虚函数,由于vtable指针被覆盖了,因此可能会访问一个不同的地址(指向被利用的代码)。或者,如果该指针用来写入内存,其它的数据结构就有可能损坏了。一旦该指针成为迷途指针,即使这段内存是只读的,仍然会导致信息的泄露(如果感兴趣的数据放在下一个数据结构里面,恰好分配在这段内存之中)或者访问权限的增加(如果现在不可使用的内存恰恰被用来安全检测).
避免迷途指针的错误
避免迷途指针,有一种受欢迎的方法——即使用智能指针(Smart pointer)。智能指针使用引用计数来回收对象。一些其它的技术包括tombstone法和locks-and-keys法。
另外,可以使用 DieHard 内存分配器,它虚拟消除了类似其它内存错误(不合法或者两次释放内存)的迷途指针错误。
还有一种办法是贝姆垃圾收集器,一种保守的垃圾回收方法,能够替代C和C++中标准内存分配函数。这种方法完全消除了迷途指针的错误,通过去除内存释放的函数代之以垃圾回收器完成对象的回收。
像Java语言,迷途指针这样的错误是不会发生的,因为Java中没有明确地重新分配内存的机制。而且垃圾回收器只会在对象的引用数为零时重新分配内存。
迷途指针的检测
为了能发现迷途指针,一种普遍的编程技术——一旦指针指向的内存空间被释放,就立即把该指针置为空指针或者为一个非法的地址。当空指针被重新引用时,此时程序将会立即停止,这将避免数据损坏或者某些无法预料的后果。这将使接下来的编程过程产生的错误变得容易发现和解决了。这种技术在该指针有多个复制时就无法起到应有的作用了。
一些调试器会自动地用特定的模式来覆盖已经释放的数据,如0xDEADBEEF (Microsoft's Visual C/C++ 调试器,例如,根据哪种类型被释放采用 0xCC,0xCD 或者 0xDD)。这种方法通过将数据无用化,来防止已经释放的数据重新被使用。这种方法的作用是非常显著的 (该模式可以帮助程序来区分哪些内存是刚刚释放的)。
某些工具,如Valgrind, Mudflap或者 LLVM可以用来检测迷途指针的使用。
总的来说,迷途指针对C程序安全性影响巨大,是C程序员必须谨慎处理的一个问题。相信本文所述对大家C程序设计有一定的借鉴价值。
本文向大家介绍C语言 函数指针(指向函数的指针)详解,包括了C语言 函数指针(指向函数的指针)详解的使用技巧和注意事项,需要的朋友参考一下 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就
本文向大家介绍c++ 智能指针基础详解,包括了c++ 智能指针基础详解的使用技巧和注意事项,需要的朋友参考一下 简介 在现代 C++ 编程中,标准库包含了智能指针(Smart pointers)。 智能指针用来确保程序不会出现内存和资源的泄漏,并且是"异常安全"(exception-safe)的。 智能指针的使用 智能指针定义在头文件 memory 里的命名空间 std 中。它对于资源获取即初始化
本文向大家介绍C++智能指针实例详解,包括了C++智能指针实例详解的使用技巧和注意事项,需要的朋友参考一下 本文通过实例详细阐述了C++关于智能指针的概念及用法,有助于读者加深对智能指针的理解。详情如下: 一、简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没
本文向大家介绍详解C语言中的常量指针和指针常量,包括了详解C语言中的常量指针和指针常量的使用技巧和注意事项,需要的朋友参考一下 概述 对于新手来说,指针在c语言里总是一个非常难以理解的概念。在这篇文章中,我们将解释常量指针,指针常量,const pointer to const(ps:楼主以为这可以翻译成指向常量的常量指针)的区别 常量指针 让我们先来理解什么是常量指针。常量指针是指指针指向的地址
学习 C++ 的指针既简单又有趣。通过指针,可以简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C++ 程序员,学习指针是很有必要的。 正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。请看下面的实例,它将输出定义的变量地址:#include <iostr
本文向大家介绍C语言中的指针以及二级指针代码详解,包括了C语言中的指针以及二级指针代码详解的使用技巧和注意事项,需要的朋友参考一下 很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家: 1.什么是“指针”: 在执行C程序的时候,由于我们的数据是存储在内存中的。所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的内存地址是多少,换言之,C程序通过已知的内存地址到相应的内