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

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

最佳答案

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

这个概念是您可能会意外访问但不应该访问的内存标有非常明显的模式。一些最常见的是 0xCDCDCDCD0xFDFDFDFD ,尽管 0xDDDDDDDD0xFEEEFEEE 也很容易遇到。经典编译器(不确定是否仍然使用它)喜欢 0xDEADBEEF 。您将在其中看到保护字节的情况和位置的 Here's a pretty good write-up

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

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

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

没有虚拟机/运行时迫使您保持在某些内存限制内,如果可以很容易地访问您不应该的内存。例如:

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

prefix-increment 会导致你跑出数组的末尾并访问 values[10] ,一个无效的索引。有时这可能会立即导致访问冲突并停止您的程序,有时它可能是您被允许访问的内存并且该值将被添加到 output ,这可能会导致 output 溢出和应用程序其余部分的意外行为.

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

关于c++ - 特殊指针值 0xFEEEFEF6,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17072441/

10-12 22:17
查看更多