我知道编译器有时会使用某些模式初始化内存,例如 0xCD
和 0xDD
。我想知道的是 何时 以及 为什么 会发生这种情况。
什么时候
这是特定于使用的编译器吗?
malloc/new
和 free/delete
在这方面的工作方式相同吗?
它是特定于平台的吗?
会不会出现在其他操作系统上,比如 Linux
或者 VxWorks
?
为什么
我的理解是这只发生在 Win32
调试配置中,它用于检测内存溢出并帮助编译器捕获异常。
你能给出任何实际例子来说明这个初始化是如何有用的吗?
我记得读过一些东西(可能在 Code Complete 2 中)说在分配内存时最好将内存初始化为已知模式,并且某些模式会在 Win32
中触发中断,这将导致调试器中显示异常.
这有多便携?
原文由 LeopardSkinPillBoxHat 发布,翻译遵循 CC BY-SA 4.0 许可协议
微软编译器在为调试模式编译时用于各种无主/未初始化内存的快速总结(支持可能因编译器版本而异):
免责声明:表格来自我周围的一些笔记——它们可能不是 100% 正确(或连贯)。
其中许多值在 vc/crt/src/dbgheap.c 中定义:
还有几次,调试运行时会用已知值填充缓冲区(或缓冲区的一部分),例如
std::string
分配中的“松弛”空间或传递给的缓冲区fread()
。这些情况使用一个名为_SECURECRT_FILL_BUFFER_PATTERN
的值(在crtdefs.h
中定义)。我不确定它是何时引入的,但它至少在 VS 2005 (VC++8) 的调试运行时中。最初,用于填充这些缓冲区的值是
0xFD
- 与无人区使用的值相同。但是,在 VS 2008 (VC++9) 中,该值更改为0xFE
。我认为这是因为在某些情况下,填充操作可能会超出缓冲区的末尾,例如,如果调用者传入的缓冲区大小对于fread()
来说太大。在这种情况下,值0xFD
可能不会触发检测此溢出,因为如果缓冲区大小仅大 1,则填充值将与用于初始化该金丝雀的无人土地值相同。无人区没有变化意味着超支不会被注意到。所以在 VS 2008 中更改了填充值,这样这种情况就会改变无人区金丝雀,导致运行时检测到问题。
正如其他人所指出的,这些值的关键属性之一是,如果取消引用具有这些值之一的指针变量,则会导致访问冲突,因为在标准 32 位 Windows 配置中,用户模式地址不会高于 0x7fffffff。