未初始化的内存用于调试的常见值是什么?

时间:2016-08-26 05:23:16

标签: c++ c debugging memory assembly

很久以前我学会了用0xDEADBEEF填充未使用/未初始化的内存,以便在调试器或崩溃报告中,如果我看到该值,我知道我正在查看未初始化的内存。我从崩溃报告中看到iOS使用0xBBADBEEF

人们使用了哪些其他创造性价值观?任何特定的价值观都有任何特定的好处吗?

变成单词的价值观最明显的好处是,至少在大多数人看来,如果这些单词都是他们的语言,那么很容易突出,因为某些严格的数值不太可能突出。

但是,也许有其他理由选择数字?例如,奇数可能会使处理器(68000)崩溃,例如在某些内存访问时崩溃,因此最好选择0x0BADBEEF而不是0xBADBEEF0。他们的任何其他值(可能是处理器特定的)是否具有使用未初始化内存的具体好处?

2 个答案:

答案 0 :(得分:7)

一般来说,你想要一个不太可能发生在"工作"当解释为整数,指针或字符串时。所以,这里有一些约束:

  • 不要使用的值是最小的"通常"的倍数。目标架构上的对齐方式。对于x86,即4(字节),因此没有可被4整除的值。这可确保如果将值解释为指针,则显然不正确。如果你使用非x86架构,你甚至可以使用一个值,如果用作指针,会导致对齐陷阱。

  • 不要使用可能合理地为小(正或负)整数的值。你的典型" int" C程序中的变量永远不会超过1,000左右,所以不要使用小数字作为空数据填充。

  • 不要使用完全由有效ASCII字符组成的值。确保高位设置在那里至少有一个字节。现在,您要确保它们不是有效的UTF-8或可能是UTF-16值。

  • 该值中没有任何零字节。太多的情况下,这将有助于"有用"防止程序崩溃 - 终止字符串,给非int字段赋予合理的值等等。

  • 不要使用单个(或两个)字节值,一遍又一遍地重复。使用全字长度模式可以更容易地确定野指针最终指向它的位置,至少缩小哪些操作将其从模式的开头偏移。

  • 不要使用映射到"典型"的有效地址的值。处理。如果设置了最高位,那么在你的进程增长到足以使其成为有效地址之前,它通常会占用大量的malloc()。

也许不足为奇的是,像0xDEADBEEF这样的模式基本上满足了所有这些要求。

答案 1 :(得分:5)

像这样的值的一个技术术语是"毒药值"。

形成英文单词的十六进制数字称为Hexspeak。 Wikipedia's Hexspeak article几乎回答了这个问题,编写了许多用于各种事物的已知常量,包括几个用作毒药值/金丝雀/健全性检查的常量,以及其他用途,如错误代码或IPv6地址。

我似乎记得0xBADF00D的一些变体。 (也许像你的第二个例子一样重复写信)。

还有0xDEADC0DE。 (谷歌搜索我已经看过这个用过的地方发现上面链接的维基百科文章。)

十六进制中的其他英语单词我看过:Java .class文件使用0xCAFEBABE作为幻数(文件的前4个字节)。作为一个游戏,我猜,Jikes JVM使用0xDEADBABE作为健全性检查常量。

显然Java并不是0xCAFEBABE的第一个用户。维基百科说" It was originally created by NeXTSTEP developers as a reference to the baristas at Peet's Coffee & Tea",并且在之前开发Java 的人们使用了他们想到的名字" Java"。所以它并没有出自Java - >咖啡(如果有其他方式),它只是普通的非女权主义科技文化。 :(

re:update:选择一个好的价值。对于毒性值(不是错误代码),您希望所有字节都不同,而不是0x000xFF,因为这些可能是错误的单字节存储的最可能值。这尤其适用于堆栈金丝雀(用于检测缓冲区溢出)或其他检测到它没有被覆盖的情况很重要。

你对选择奇数值的猜测很有意义。 在典型流程的虚拟内存布局中不是有效的内存地址是一个很大的优势。尽早失败是调试的最佳选择。无论如何,这可能意味着拥有高位设置是一个好主意,所以0x0...可能不是一个好主意。