从 C# 崩溃异常 中研究页堆布局

一:背景1.讲故事最近遇到一位朋友的程序崩溃,发现崩溃点在富编辑器 msftedit 上,这个不是重点 , 重点在于发现他已经开启了 页堆 ,看样子是做了最后的挣扎 。
0:000> !analyze -vEXCEPTION_RECORD:  (.exr -1)ExceptionAddress: 82779a9e (msftedit!CCallMgrCenter::SendAllNotifications+0x00000123)   ExceptionCode: c0000005 (Access violation)  ExceptionFlags: 00000000NumberParameters: 2   Parameter[0]: 00000001   Parameter[1]: 8351af28Attempt to write to address 8351af28...STACK_TEXT:00ffe0dc 827bda2a 8351ae88 00000000 00ffe174 msftedit!CCallMgrCenter::SendAllNotifications+0x12300ffe110 827bd731 00ffe324 00ffe174 00ffe300 msftedit!CCallMgrCenter::ExitContext+0xda00ffe120 827bde71 8351ae88 827232dc 28112f80 msftedit!CCallMgr::~CCallMgr+0x1700ffe300 8290281f 00000102 00000067 00220001 msftedit!CTxtEdit::TxSendMessage+0x20100ffe374 7576110b 00f20268 00000102 00000067 msftedit!RichEditWndProc+0x9cf00ffe3a0 757580ca 82901e50 00f20268 00000102 user32!_InternalCallWinProc+0x2b...SYMBOL_NAME:  system_windows_forms+1c45e7MODULE_NAME: System_Windows_FormsIMAGE_NAME:  System.Windows.Forms.dll0:000> !heap -p    Active GlobalFlag bits:        vrf - Enable application verifier        hpa - Place heap allocations at ends of pages    StackTraceDataBase @ 04c20000 of size 01000000 with 00001b18 traces    PageHeap enabled with options:        ENABLE_PAGE_HEAP        COLLECT_STACK_TRACES    active heaps:    + 5c20000        ENABLE_PAGE_HEAP COLLECT_STACK_TRACES      NormalHeap - 5d90000          HEAP_GROWABLE    + 5e90000        ENABLE_PAGE_HEAP COLLECT_STACK_TRACES      NormalHeap - 4960000          HEAP_GROWABLE HEAP_CLASS_1      ...由于 页堆 和 NT堆 的内存布局完全不一样 , 这一篇结合我的了解以及 windbg 验证来系统的介绍下 页堆 。
二:对 页堆 的研究1. 案例演示为了方便讲述,先上一段测试代码 。
int main(){ HANDLE h = HeapCreate(NULL, 0, 100); int* ptr = (int*)HeapAlloc(h, 0, 9); printf("ptr= %x", ptr); DebugBreak();}接下来用 gflags 开启下页堆 。
PS C:\Users\Administrator\Desktop> gflags -i ConsoleApplication1.exe +hpaCurrent Registry Settings for ConsoleApplication1.exe executable are: 02000000    hpa - Enable page heap然后将程序跑起来,可以看到返回的 handle 句柄 。

从 C# 崩溃异常 中研究页堆布局

文章插图
2. 页堆布局研究接下来用 windbg 的 !heap -p 命令观察页堆 。
0:000> !heap -p    Active GlobalFlag bits:        hpa - Place heap allocations at ends of pages    StackTraceDataBase @ 042e0000 of size 01000000 with 0000000e traces    PageHeap enabled with options:        ENABLE_PAGE_HEAP        COLLECT_STACK_TRACES    active heaps:    + 5b0000        ENABLE_PAGE_HEAP COLLECT_STACK_TRACES      NormalHeap - 710000          HEAP_GROWABLE    + 810000        ENABLE_PAGE_HEAP COLLECT_STACK_TRACES      NormalHeap - 510000          HEAP_GROWABLE HEAP_CLASS_1    + 56e0000        ENABLE_PAGE_HEAP COLLECT_STACK_TRACES      NormalHeap - 5aa0000          HEAP_CLASS_1

推荐阅读