特殊指针值0xFEEEFEF6

时间:2013-06-12 18:14:38

标签: c++ visual-studio c++11

我在Visual Studio 2012中读取位置0xFEEEFEF6时遇到了访问冲突(使用2012年11月的CTP编译器),这在C ++ 11并发实现的深处。

这个值有什么特别的含义吗?查看Wikipedia我发现了类似的条目( 0xFEEEFEEE 0xFEEDFACE )。

1 个答案:

答案 0 :(得分:6)

0xFEEEFEF6本身没有特殊含义,但它可能基于MSVC喜欢围绕堆分配的“保护字节”段之一。正如Jan Dvorak所指出的那样,它可能超过了某个结尾的8个字节,很可能是超过数组末尾的2个指针。

这个概念是你可能偶然访问的内存,但不应该,标记非常明显的模式。一些最常见的是0xCDCDCDCD0xFDFDFDFD,但0xDDDDDDDD0xFEEEFEEE也很容易遇到。经典编译器(不确定是否仍然使用它)喜欢0xDEADBEEFHere's a pretty good write-up个案例和位置,你会看到保护字节。

在段错误(访问冲突)中看到这些的两个最常见原因通常是访问已经释放并超出边界的内存,尤其是在指针数组中。用于保护数据的大多数值如果要显示在应用程序中则无效(否则您将不会在0x000000000xCDCDCDCD获得一块内存,这些值很好在你的堆所在的虚拟地址空间之外)。了解常见问题可以节省大量的调试时间。

请注意,只有极少数/无异常,这些保护字节仅出现在调试版本中。每次分配/解除分配时写入具有特殊模式的存储器(实际上,写入的内存比分配的内存大得多,因为大多数防护模式出现在分配的块的边界上)是相当昂贵的,不应该在运行时完成。如果在调试版本中遇到类似这样的问题,则可能会从发布版本中获得看似随机(未定义)的地址。你也可能不幸的是,合法的地址最终会被错误地抓住,这可能导致各种堆损坏。

由于保护字节未在发布版本中显示,因此您无法像NULL那样检查它们,并将其用作代码中的条件。相反,智能指针和容器可以帮助您正确管理内存并避免错误访问。虽然偶尔会很烦人,但智能指针非常有助于避免这样的问题。请注意,某些类型的访问冲突,特别是缓冲区溢出,被视为一整类安全漏洞,因为它们出现的频率很高。

如果没有VM /运行时强制您保持在某些内存限制内,如果可以非常轻松地访问内存,则不应该这样做。例如:

int values[10];
int output = 0;
int length = 10;
while (int i <= length) {
    output += values[++length];
}

前缀增量将导致您运行数组的末尾并访问values[10],这是一个无效的索引。有时,这可能会立即导致访问冲突并暂停您的程序,有时可能是您可以访问的内存,并且该值将添加到output,这可能会导致output上的溢出通过应用程序的其余部分出现意外行为。

保留字节存在,以便您的段错误或增量在调试时具有可重复的值并尽可能明显。