233

在 Visual Studio 中,我们都有过“baadf00d”,在运行时检查 C++ 调试器中的变量时见过“CC”和“CD”。

据我了解,“CC”处于调试模式仅表示内存何时被 new() 或 alloc() 和未初始化。而“CD”代表删除或释放的内存。我只在 RELEASE 版本中看到过“baadf00d”(但我可能错了)。

有时,我们会遇到处理内存泄漏、缓冲区溢出等情况,这些信息会派上用场。

有人愿意指出何时以及以何种模式将内存设置为可识别的字节模式以进行调试?

4

3 回答 3

345

此链接有更多信息:

https://en.wikipedia.org/wiki/Magic_number_(programming)#Debug_values

* 0xABABABAB : Microsoft 的 HeapAlloc() 用于在分配堆内存后标记“无人区”保护字节
* 0xABADCAFE : 启动此值以初始化所有空闲内存以捕获错误指针
* 0xBAADF00D : 被微软的 LocalAlloc(LMEM_FIXED) 用来标记未初始化的分配堆内存
* 0xBADCAB1E : 与调试器的连接断开时返回到 Microsoft eVC 调试器的错误代码
* 0xBEEFCACE:被 Microsoft .NET 用作资源文件中的幻数
* 0xCCCCCCCC : 被微软的 C++ 调试运行时库用来标记未初始化的堆栈内存
* 0xCDCDCDCD : 被微软的 C++ 调试运行时库用来标记未初始化的堆内存
* 0xDDDDDDDD : 被微软的 C++ 调试堆用来标记释放的堆内存
* 0xDEADDEAD:用户手动启动崩溃时使用的 Microsoft Windows STOP 错误代码。
* 0xFDFDFDFD : 被微软的 C++ 调试堆用来标记分配堆内存前后的“无人区”保护字节
* 0xFEEEFEEE:被微软的 HeapFree() 用来标记释放的堆内存
于 2008-09-24T14:14:34.710 回答
114

实际上,调试分配中添加了很多有用的信息。这张表更完整:

http://www.nobugs.org/developer/win32/debug_crt_heap.html#table

HeapAlloc() 之后的地址偏移量 malloc() 之后 free() HeapFree() 之后的地址
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Win32堆信息
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Win32堆信息
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448 Ptr 到下一个 CRT 堆块(分配时间较早)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 Ptr 到上一个 CRT 堆块(稍后分配)
0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE malloc() 调用的文件名
0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE malloc() 调用的行号
0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDDDDDD 0xFEEEFEEE 要 malloc() 的字节数
0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDD 0xFEEEFEEE 类型(0=释放,1=正常,2=CRT使用等)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE 请求编号,从0增加
0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE 无人区
0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE 你想要的 8 个字节
0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE 你想要的 8 个字节
0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE 无人区
0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE Win32 堆分配四舍五入到 16 字节
0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32堆簿记
0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32堆记账
0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Win32堆簿记
0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Win32堆簿记
0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Win32堆簿记
0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEEFEEE Win32堆簿记
0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32堆簿记
0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32堆簿记
于 2008-12-09T17:41:30.450 回答
6

0xCC特别是,0xCD这些是1980 年代英特尔8088 / 8086处理器指令集的遗留物。是软件中断操作码 0xCC的特例。特殊的单字节版本允许程序生成中断 3INT 0xCD0xCC

尽管软件中断号原则上是任意的,INT 3但传统上用于调试器中断断点功能,这一惯例一直保留到今天。每当启动调试器时,它都会安装一个中断处理程序,INT 3以便在执行该操作码时触发调试器。通常,它会暂停当前正在运行的程序并显示交互式提示。

通常,x86INT操作码是两个字节:0xCD后跟从 0 到 255 的所需中断号。现在,尽管您可以发出0xCD 0x03INT 3但英特尔决定添加一个特殊版本——0xCC没有额外的字节——因为操作码必须只有一个字节才能用作未使用内存的可靠“填充字节”。

这里的重点是在处理器错误地跳转到不包含任何预期指令的内存中时允许优雅恢复。多字节指令不适合此目的,因为错误跳转可能会落在任何可能的字节偏移处,它必须继续使用正确形成的指令流。

显然,单字节操作码对此工作很简单,但也可能有一些奇怪的例外:例如,考虑到填充序列0xCDCDCDCD(也在本页中提到),我们可以看到它相当可靠,因为无论指令指针落在哪里(除了最后一个填充字节),CPU可以继续执行有效的两字节x86 指令CD CD,在这种情况下用于生成软件中断 205 (0xCD)。

更奇怪的是,虽然CD CC CD CC是 100% 可解释的 - 给出INT 3INT 204- 序列CC CD CC CD不太可靠,如图所示只有 75%,但当作为 int 大小的内存填充符重复时通常为 99.99%。

来自同时代 8088/8086 指令集手册的页面显示 INT 指令
宏汇编器参考, 1987

于 2018-01-15T00:25:48.377 回答