43

对于 32 位系统(无论是 Linux、Mac OS或 Windows,PowerPC还是 x86)的 C++ 开发,我已经初始化了原本未定义的指针(例如,它们不能立即获得正确的值),如下所示:

int *pInt = reinterpret_cast<int *>(0xDEADBEEF);

(为了节省打字和干燥,右手边通常是一个常数,例如 BAD_PTR。)

如果 pInt 在获得正确值之前被取消引用,那么它将在大多数系统上立即崩溃(而不是在某些内存被覆盖或进入非常长的循环时崩溃很久)。

当然,行为取决于底层硬件(从用户进程的奇数地址 0xDEADBEEF 获取 4 字节整数可能是完全有效的),但是对于我迄今为止开发的所有系统,崩溃都是 100% 可靠的( Mac OS 68xxx、Mac OS PowerPC、Linux Redhat Pentium、Windows GUI Pentium、Windows 控制台 Pentium)。例如,在 PowerPC 上,从奇数地址获取 4 字节整数是非法的(总线故障)。

在 64 位系统上这有什么好的价值?

4

12 回答 12

71

0xBADC0FFEE0DDF00D

于 2009-08-11T01:27:33.023 回答
55

根据 Wikipedia,BADC0FFEE0DDF00D 在 IBM RS/6000 64 位系统上用于指示未初始化的 CPU 寄存器。

于 2009-08-11T01:28:28.780 回答
27

大多数当前的 64 位系统只允许您使用地址空间的最低 2 48 –2 52位;地址的高位必须全为零。一些芯片(例如 amd64)也让你使用最高的2 48 –2 52。这些范围之外的地址永远不能映射到可访问的内存;硬件根本不允许。

因此,我建议您使用接近 2 63的值,这与任何一个可能可用的空间都相去甚远。如果前四位十六进制数字是 7ff8,则该值将是双精度浮点 NaN,这很方便。所以我建议的可爱的十六进制短语是 0x7FF8BADFBADFBADF。

顺便说一句,您真的不想使用接近 0 的值,因为这使得很难将 NULL 的偏移取消引用(例如结构成员访问)与毒模式的取消引用区分开来。

于 2010-08-02T20:40:19.893 回答
25

通常,您编写的确切模式并不重要,重要的是您可以识别模式以确定问题发生在哪里。碰巧的是,在 Linux 内核中,通常会选择这些地址,以便在取消引用地址时可以捕获它们。

在include/linux/poison.h中查看 Linux 内核。该文件包含许多不同内核子系统的不同毒值。没有一个合适的毒值。

此外,您可以检查 Linux 内核源代码树中的每个架构包含文件,以获取有关特定架构上使用的内容的信息。

于 2010-08-02T15:20:56.047 回答
14

我假设您已经打折了 NULL(即 0 没有类型转换)。这绝对是最安全的选择,因为理论上,一个有效的指针可以指向内存地址 0xDEADBEEF(或任何其他非 NULL 内存地址)。

于 2009-08-11T01:27:19.780 回答
13

0xDEADBEEFBAADF00D可能会奏效。

于 2009-08-11T01:26:31.963 回答
8

我没有给你一个好的选择,但这里有一个十六进制单词列表,你可以用它来制作你的短语。

于 2009-08-11T01:29:11.460 回答
5

我认为两个 0xDEADBEEF 应该足够了。

于 2010-08-02T15:02:37.597 回答
3

我看到几个答案声称 NULL 是一个不错的选择,但我不同意。

NULL 通常用作函数的有效返回值。它表示失败返回或未知值。这与“未初始化的指针”的含义不同。

在代码上使用调试器并看到 NULL 会留下两种可能性:指针从未初始化或内存分配失败。

将未初始化的指针设置为 0xDEADBEEF 或 64 位等效值意味着 NULL 指针表示有意的值。

于 2009-08-11T02:50:43.887 回答
2

当然,这取决于操作系统和环境。我也不认为 0xDEADBEEF 在任意 32 位系统中一定是一个坏指针。

实际上,任何现代操作系统都应该对进程内存的前几页进行访问保护,因此 NULL 应该是一个很好的无效指针值。方便的是,它已经为您预先定义了。

于 2009-08-11T01:31:44.423 回答
1

0x42可以在 32 位和 64 位上工作吗?(它仍然应该触发崩溃,因为它与 NULL 指针足够接近,并且鉴于它相当大,您可能不会在结构指针为 NULL 的结构字段的常规取消引用中使用它)。

于 2009-08-11T01:29:46.517 回答
1

由于我工作的系统基本上是在x86_64平台上运行的,所以我使用的值是:

0xDEADBEEFDEADBEEF

原因是:

  • 在 x86_64 平台上,当前实现中只有低 48 位用于虚拟内存地址,这意味着任何大于 2^48 的值都应该起作用:https ://en.wikipedia.org/wiki/X86-64
  • 正如0xDEADBEEF在 32 位中为此目的已经众所周知的那样,0xDEADBEEFDEADBEEF在 64 位中只是更“向后兼容”
于 2019-05-28T13:45:01.217 回答