• Windows C++代码heap分析详解


    上次写了一篇文章,Windows代码heap内存分析实战

    由于时间的关系,写的不是很详细,于是有朋友建议写的详细些,于是有了本文。

    Windows C++代码heap分析详解

    Windows代码占用的内存主要是堆和栈,其中栈内存又被称为自动内存,一般为系统自动管理,所以常见的问题主要发生在堆内存上。系统中如果分配了堆内存而不释放,或者错误释放,都会产生问题。

    首先来分析一下堆内存的主要结构:

    对于普通的堆:

    1. CreateHeap -> creates a _HEAP

    2. AllocHeap -> creates a _HEAP_ENTRY

     

    对于页堆 (gflags.exe /i +hpa)

     

    1. CreateHeap -> creates a _DPH_HEAP_ROOT (+ _HEAP + 2x _HEAP_ENTRY)

    2. AllocHeap -> creates a _DPH_HEAP_BLOCK

    也就是说对于页堆,有额外的数据表征其内容,当让,对于同样堆分析命令,对于两种堆也会输出不同的内容。

    对于普通的堆,分别执行的分析命令和结果如下:

    0:001> !heap -s

    NtGlobalFlag enables following debugging aids for new heaps:

        validate parameters

        stack back traces

      Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast

                        (k)     (k)    (k)     (k) length      blocks cont. heap

    -----------------------------------------------------------------------------

    00170000 58000062    1024     64     64     12     3     1    0      0   L 

    00270000 58001062      64     24     24     11     1     1    0      0   L 

    00280000 58008060      64     12     12     10     1     1    0      0     

    00370000 58001062      64     28     28      9     1     1    0      0   L 

    00390000 58001062      64     56     56      5     2     1    0      0     

    003a0000 58001062    1088     72     72     16     3     2    0      0   L 

    003f0000 58001062      64     20     20      5     2     1    0      0   L 

    01a20000 58001062      64     20     20      1     1     1    0      0   L 

    02090000 58001062      64     12     12      4     1     1    0      0   L 

    -----------------------------------------------------------------------------

    0:001> !heap -p

        Active GlobalFlag bits:

            hpc - Enable heap parameter checking

            ust - Create user mode stack trace database

        StackTraceDataBase @ 00430000 of size 01000000 with 0000037f traces

        active heaps:

     - 170000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED

     - 270000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

     - 280000

              HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_8

     - 370000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

     - 390000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

     - 3a0000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

     - 3f0000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

     - 1a20000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

     - 2090000

              HEAP_GROWABLE HEAP_TAIL_CHECKING_ENABLED HEAP_FREE_CHECKING_ENABLED HEAP_CLASS_1

    0:001> !heap -stat

    _HEAP 003a0000

         Segments            00000002

             Reserved  bytes 00110000

             Committed bytes 00012000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 00170000

         Segments            00000001

             Reserved  bytes 00100000

             Committed bytes 00010000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 00390000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 0000e000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 00370000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 00007000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 00270000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 00006000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 01a20000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 00005000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 003f0000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 00005000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 02090000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 00003000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    _HEAP 00280000

         Segments            00000001

             Reserved  bytes 00010000

             Committed bytes 00003000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    对于页堆堆,分别执行的分析命令和结果如下:

    0:001> !heap -s

      Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast

                        (k)     (k)    (k)     (k) length      blocks cont. heap

    -----------------------------------------------------------------------------

    00270000 00000002    1024     12     12      4     1     1    0      0   L 

    00380000 00001002      64     24     24     16     1     1    0      0   L 

    00390000 00008000      64     12     12     10     1     1    0      0     

    003e0000 00001002      64     12     12      4     1     1    0      0   L 

    018e0000 00001002      64     12     12      4     1     1    0      0   L 

    01ad0000 00001002      64     32     32     24     1     1    0      0   L 

    02020000 00001002      64     12     12      4     1     1    0      0   L 

    02130000 00001002      64     12     12      4     1     1    0      0   L 

    02bd0000 00001002      64     12     12      4     1     1    0      0   L 

    02ce0000 00001002      64     12     12      4     1     1    0      0   L 

    -----------------------------------------------------------------------------

    0:001> !heap -p

        Active GlobalFlag bits:

            hpa - Place heap allocations at ends of pages

        StackTraceDataBase @ 00430000 of size 01000000 with 00000376 traces

        PageHeap enabled with options:

            ENABLE_PAGE_HEAP

            COLLECT_STACK_TRACES

        active heaps:

        + 170000

            ENABLE_PAGE_HEAP COLLECT_STACK_TRACES

          NormalHeap - 270000

              HEAP_GROWABLE

    ReadMemory error for address eeddccee

    Use `!address eeddccee' to check validity of the address.

    0:001> !heap -stat

    ReadMemory error for address eeddccee

    Use `!address eeddccee' to check validity of the address.

    _HEAP 00170000

         Segments            00000001

             Reserved  bytes 00100000

             Committed bytes 00003000

         VirtAllocBlocks     00000000

             VirtAlloc bytes 00000000

    从分析结果我们可以看出!heap  -p 命令对于不同的堆输出的内容是不同的,对于普通的堆,!heap –s !heap –p 产生相同的地址,而对于页堆,他们的输出就有了显著的不同 。另外对于普通的堆,heap handleheap address 一样,而对于页堆,其也有很大的区别。

    另外值得一提的是!heap –p –a 这条神奇命令,别看这条命令带-p 其实这条命令根本不需要开启页堆选项,只要有 +ust就行了

    !heap -p -a [UserAddr....UserAddr+AlloSize]

     

    正常情况下这条命令可以打相应的callstack.

     

  • 相关阅读:
    大部分人都会做错的经典JS闭包面试题
    20071109 QQ群:ITIL和ITSM 聊天记录,欢迎大家加入QQ群:48132184
    模式窗口window.open造成Session丢失的解决方法
    Server.Transfer 方法如何传递复杂的参数
    小游戏测试你的情商
    VS.Net 开发 MSN一样缓慢出来的提示信息的方法
    Javascript 技巧大全
    ASP.NET 2.0,无刷新页面新境界! 【转】
    ASP.NET AJAX入门系列【转】
    asp.net2.0+ajax开发的无刷新聊天室Demo【转】
  • 原文地址:https://www.cnblogs.com/pugang/p/2696845.html
Copyright © 2020-2023  润新知