在计算机编程领域中，**迷途指针**，或称**悬空指针**、**野指针**，指的是不指向任何合法的对象的指针。

当所指向的对象被释放或者收回，但是对该指针没有作任何的修改，以至于该指针仍旧指向已经回收的内存地址，此情况下该指针便称迷途指针。若操作系统将这部分已经释放的内存重新分配给另外一个进程，而原来的程序重新引用现在的迷途指针，则将产生无法预料的后果。因为此时迷途指针所指向的内存现在包含的已经完全是不同的数据。通常来说，若原来的程序继续往迷途指针所指向的内存地址写入数据，这些和原来程序不相关的数据将被损坏，进而导致不可预料的程序错误。这种类型的程序错误，不容易找到问题的原因，通常会导致記憶體區段錯誤（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 now becomes a dangling pointer \*/
 cp = NULL; /\* cp is no longer dangling \*/
 /\* ... \*/
}

```

有个常见的错误是当返回一个基于栈分配的局部变量的地址时，一旦调用的函数返回，分配给这些变量的空间将被回收，此时它们拥有的是"垃圾值"。

```
int \* func ( void )
{
 int num = 1234;
 /\* ... \*/
 return &num;
}

```

在调用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: static variables 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
}

```

迷途指针导致的安全漏洞
-----------

如同缓存溢出错误，迷途指针/野指针这类错误经常会导致安全漏洞。 例如，如果一个指针用来调用一个虚函数，由于vtable（英语：）指针被覆盖了，因此可能会访问一个不同的地址（指向被利用的代码）。或者，如果该指针用来写入内存，其它的数据结构就有可能损坏了。一旦该指针成为迷途指针，即使这段内存是只读的，仍然会导致信息的泄露（如果感兴趣的数据放在下一个数据结构里面，恰好分配在这段内存之中）或者访问权限的增加（如果现在不可使用的内存恰恰被用来安全检测）。

避免迷途指针的错误
---------

避免迷途指针，有一种受欢迎的方法——即使用智能指针（）。智能指针使用引用计数来回收对象。一些其它的技术包括tombstone（英语：）法和locks-and-keys（英语：）法。

另外，可以使用 DieHard 内存分配器，它虚拟消除了类似其它内存错误（不合法或者两次释放内存）的迷途指针错误。

还有一种办法是貝姆垃圾收集器，一种保守的垃圾回收方法，能够替代C和C++中标准内存分配函数。这种方法完全消除了迷途指针的错误，通过去除内存释放的函数代之以垃圾回收器完成对象的回收。

像Java语言，迷途指针这样的错误是不会发生的，因为Java中没有明确地重新分配内存的机制。而且垃圾回收器只会在对象的引用数为零时重新分配内存。

迷途指针的检测
-------

为了能发现迷途指针，一种普遍的编程技术——一旦指针指向的内存空间被释放，就立即把该指针置为空指针或者为一个非法的地址。当空指针被重新引用时，此时程序将会立即停止，这将避免数据损坏或者某些无法预料的后果。这将使接下来的编程过程产生的错误变得容易发现和解决了。这种技术在该指针有多个复制时就无法起到应有的作用了。

一些调试器会自动地用特定的模式来覆盖已经释放的数据，如`0xDEADBEEF（英语：）` （Microsoft's Visual C/C++ 调试器，例如，根据哪种类型被释放采用 `0xCC`，`0xCD` 或者 `0xDD`）。这种方法通过将数据无用化，来防止已经释放的数据重新被使用。这种方法的作用是非常显著的（该模式可以帮助程序来区分哪些内存是刚刚释放的）。

| 值 | 名字 | 描述 |
| --- | --- | --- |
| 0xCD | Clean Memory | Allocated memory via malloc or new but never written by the application. |
| 0xDD | Dead Memory | Memory that has been released with delete or free. Used to detect writing through dangling pointers. |
| 0xFD | Fence Memory | Also known as "no mans land." This is used to wrap the allocated memory (surrounding it with a fence) and is used to detect indexing arrays out of bounds or other accesses (especially writes) past the end (or start) of an allocated block. |
| 0xCC |  | When the code is compiled with the /GZ option, uninitialized variables are automatically assigned to this value (at byte level). |
| 0xAB |  | Memory allocated by LocalAlloc(). |
| 0xBAADF00D | Bad Food | Memory allocated by LocalAlloc() with LMEM\_FIXED,but not yet written to. |
| 0xFEEEFEEE |  | OS fill heap memory, which was marked for usage, but wasn't allocated by HeapAlloc() or LocalAlloc(). Or that memory just has been freed by HeapFree(). |

某些工具，如Valgrind， Mudflap 或者 LLVM 可以用来检测迷途指针的使用。

相關條目
----

* Wild branch

外部链接
----

* Pointers and Arrays (C99)
* Topics on Pointers and Arrays
* Dangling Pointer New Hacking Technique (Security)
* Dangling pointers[永久]

参考文献
----

1. ↑  E. Berger and B. Zorn, DieHard: Probabilistic Memory Safety for Unsafe Languages （页面存档备份，存于） (DieHard website （页面存档备份，存于）)
2. ↑ .  [2009-09-21]. （原始内容存档于2007-10-24）.
3. ↑ .  [2009-09-21]. （原始内容存档于2021-03-22）.
4. ↑  Dhurjati, D. and Adve, V. Efficiently Detecting All Dangling Pointer Uses in Production Servers 的存檔，存档日期2009-03-20.

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
記憶體管理 |
| --- |
|  |
| 
* 操作系统的内存管理功能（英语：）

 |
|  |
| 手动内存管理（英语：） | 
* 静态内存分配
* C动态内存分配
* new (C++)
* delete (C++)（英语：）

 |
|  |
| 虚拟内存 | 
* 按需分页（英语：）
* 分頁表
* 分頁
* 虚拟内存压缩（英语：）

 |
|  |
| 硬件内存管理 | 
* 内存管理单元
* 轉譯後備緩衝區

 |
|  |
| 垃圾回收 | 
* 貝姆垃圾收集器
* Cheney算法
* 终止器（英语：）
* 垃圾（英语：）
* 标记压缩算法（英语：）
* 引用计数
* 强引用
* 弱引用
* 追踪垃圾回收

 |
|  |
| 記憶體分段 | 
* 保護模式
* 真實模式
* 虚拟8086模式
* X86記憶體區段

 |
|  |
| 記憶體安全 | 
* 缓冲区溢出
* 缓冲区过读
* 迷途指针
* 堆疊溢位

 |
|  |
| 针对的问题 | 
* 内存碎片化
* 内存泄漏
* 不可访问内存

 |
|  |
| 其它 | 
* 自动变量
* 内存管理国际研讨会（英语：）
* 基于区域内存管理（英语：）

 |

 |