提问人:HidekiAI 提问时间:9/24/2008 最后编辑:Glenn SlaydenHidekiAI 更新时间:10/3/2023 访问量:122719
Visual Studio C++ 和 Windows 中的调试内存填充模式是什么?
What are the debug memory fill patterns in Visual Studio C++ and Windows?
问:
在 Visual Studio 中,我们都遇到过“baadf00d”,在运行时使用 C++ 检查调试器中的变量时看到过“CC”和“CD”。
据我了解,“CC”处于 DEBUG 模式,仅用于指示内存何时被 new() 或 alloc() 并统一化。而“CD”代表删除或释放的内存。我只在 RELEASE 版本中看到过“baadf00d”(但我可能是错的)。
有时,我们会遇到内存泄漏、缓冲区溢出等情况,这些信息会派上用场。
有人会好心地指出何时以及在什么模式下将内存设置为可识别的字节模式以进行调试吗?
答:
此链接包含更多信息:
https://en.wikipedia.org/wiki/Magic_number_(编程)#Debug_values
* 0xABABABAB : Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory * 0xABADCAFE : A startup to this value to initialize all free memory to catch errant pointers * 0xBAADF00D : Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory * 0xBADCAB1E : Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger * 0xBEEFCACE : Used by Microsoft .NET as a magic number in resource files * 0xCCCCCCCC : Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory * 0xCDCDCDCD : Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory * 0xDDDDDDDD : Used by Microsoft's C++ debugging heap to mark freed heap memory * 0xDEADDEAD : A Microsoft Windows STOP Error code used when the user manually initiates the crash. * 0xFDFDFDFD : Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory * 0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory
评论
BAADF00D
BEEFCACE
BAADCAB1E
BADCAFE
DEADDEAD
0xDEADBEEF
,即使它们不属于MS的白话,也是经典0xC0EDBABE
BEA71E5
实际上,调试分配中添加了相当多的有用信息。此表更完整:
http://www.nobugs.org/developer/win32/debug_crt_heap.html#table
Address Offset After HeapAlloc() After malloc() During free() After HeapFree() Comments 0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Win32 heap info 0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Win32 heap info 0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448 Ptr to next CRT heap block (allocated earlier in time) 0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 Ptr to prev CRT heap block (allocated later in time) 0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Filename of malloc() call 0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Line number of malloc() call 0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDDDDDD 0xFEEEFEEE Number of bytes to malloc() 0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDD 0xFEEEFEEE Type (0=Freed, 1=Normal, 2=CRT use, etc) 0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE Request #, increases from 0 0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE No mans land 0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE The 8 bytes you wanted 0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE The 8 bytes you wanted 0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE No mans land 0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE Win32 heap allocations are rounded up to 16 bytes 0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32 heap bookkeeping 0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32 heap bookkeeping 0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Win32 heap bookkeeping 0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Win32 heap bookkeeping 0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Win32 heap bookkeeping 0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEEFEEE Win32 heap bookkeeping 0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32 heap bookkeeping 0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32 heap bookkeeping
特别是,这些是 1980 年代英特尔 8088/8086 处理器指令集的遗物。 是软件中断操作码INT
的特例。特殊的单字节版本允许程序生成中断 3。0xCC
0xCD
0xCC
0xCD
0xCC
尽管软件中断数原则上是任意的,但传统上用于调试器中断或断点功能,这一约定一直沿用至今。每当启动调试器时,它都会安装一个中断处理程序,以便在执行该操作码时触发调试器。通常,它将暂停当前正在运行的编程并显示交互式提示。INT 3
INT 3
通常,x86 操作码需要两个字节:后跟 0-255 之间的所需中断数。因此,尽管您可以因此发布 ,但英特尔决定添加一个特殊版本(没有额外的字节),因为操作码必须只有一个字节才能用作未使用内存的可靠“填充字节”。INT
0xCD
0xCD 0x03
INT 3
0xCC
这里的重点是,如果处理器错误地跳转到不包含任何预期指令的内存中,则允许正常恢复。多字节指令不适合此目的,因为错误的跳转可能会落在任何可能的字节偏移量处,而它必须继续使用正确格式的指令流。
显然,单字节操作码对此工作微不足道,但也可能有古怪的例外:例如,考虑到填充序列(本页也提到了),我们可以看到它是相当可靠的,因为无论指令指针落在何处(可能除了最后一个填充的字节),CPU 都可以继续执行有效的双字节 x86 指令, 在这种情况下,用于生成软件中断205(0xCD)。0xCDCDCDCD
CD CD
更奇怪的是,虽然是 100% 可解释的——给出 either 或 ——序列不太可靠,如图所示只有 75%,但当作为 int 大小的内存填充物重复时,通常为 99.99%。CD CC CD CC
INT 3
INT 204
CC CD CC CD
评论
NOP
0xCC
eb
评论