堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000

C/C++本地代码调试

堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-07, 16:12 下午

大家好:

     我又仔细看了下《软件调试》中的23章。并做了一些实验。出了个很奇怪的问题:

     如果不定义任何的调试标记!gflag -htc -hfc –hpc,New NtGlobalFlag contents: 0x00000000 那么在释放堆的时候,堆既没有被释放,也没有添加到空闲链表当中。但是当进行堆验证的时候,堆却忽然将这2个空闲块释放了。。。

     源代码:就是分配了1个私有堆,之后再从这个堆上分配了2次堆块,并且均释放。

        void heaperr()
       {
                HANDLE hHeap=NULL;
                int   bRet = false;
                void* p = NULL;

               hHeap=HeapCreate(0, 4096, 0);
               p = HeapAlloc(hHeap, 0, 128);
               bRet=HeapFree(hHeap, 0, p);

                p = HeapAlloc(hHeap, 0, 256);
                bRet=HeapFree(hHeap, 0, p);


                bRet=HeapValidate(hHeap, 0, NULL); 
                bRet=HeapDestroy(hHeap);

               return ;
         }

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-07, 16:14 下午

这是第二次分配堆块512B,这里也可以看到上次分配的堆块128B并没有被释放

0:000> !heap 3a0000 -a

Index   Address  Name      Debugging options enabled

  5:   003a0000

    Segment at 003a0000 to 003b0000 (00003000 bytes committed)

    Flags:                00001002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00100000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000200

    DeCommit Total Thres: 00002000

    Total Free Size:      000001fd

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003a0608

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003a0050

    UCR FreeList:        003a0598

    FreeList Usage:      00000000 00000000 00000000 00000000

    FreeList[ 00 ] at 003a0178: 003a2020 . 003a2020 

        003a2018: 00108 . 00fe8 [10] - free

    Segment00 at 003a0640:

        Flags:           00000000

        Base:            003a0000

        First Entry:     003a0680

        Last Entry:      003b0000

        Total Pages:     00000010

        Total UnCommit:  0000000d

        Largest UnCommit:0000d000

        UnCommitted Ranges: (1)

            003a3000: 0000d000

 

    Heap entries for Segment00 in Heap 003a0000

        003a0000: 00000 . 00640 [01] - busy (640)

        003a0640: 00640 . 00040 [01] - busy (40)

        003a0680: 00040 . 01808 [01] - busy (1800)

        003a1e88: 01808 . 00088 [01] - busy (80)

        003a1f10: 00088 . 00108 [01] - busy (100)

        003a2018: 00108 . 00fe8 [10]

        003a3000:      0000d000      - uncommitted bytes.

 

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-07, 16:15 下午

这是第二次释放堆块,这里看出,和第一次一样堆没有释放,而且在堆空闲链表中也没有记录。

0:000> !heap 003a0000 -a

Index   Address  Name      Debugging options enabled

  5:   003a0000

    Segment at 003a0000 to 003b0000 (00003000 bytes committed)

    Flags:                00001002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00100000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000200

    DeCommit Total Thres: 00002000

    Total Free Size:      000001fd

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003a0608

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003a0050

    UCR FreeList:        003a0598

    FreeList Usage:      00000000 00000000 00000000 00000000

    FreeList[ 00 ] at 003a0178: 003a2020 . 003a2020 

        003a2018: 00108 . 00fe8 [10] - free

    Segment00 at 003a0640:

        Flags:           00000000

        Base:            003a0000

        First Entry:     003a0680

        Last Entry:      003b0000

        Total Pages:     00000010

        Total UnCommit:  0000000d

        Largest UnCommit:0000d000

        UnCommitted Ranges: (1)

            003a3000: 0000d000

 

    Heap entries for Segment00 in Heap 003a0000

        003a0000: 00000 . 00640 [01] - busy (640)

        003a0640: 00640 . 00040 [01] - busy (40)

        003a0680: 00040 . 01808 [01] - busy (1800)

        003a1e88: 01808 . 00088 [01] - busy (80)

        003a1f10: 00088 . 00108 [01] - busy (100)

        003a2018: 00108 . 00fe8 [10]

        003a3000:      0000d000      - uncommitted bytes.

 

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-07, 16:15 下午

这是第二次释放堆块,这里看出,和第一次一样堆没有释放,而且在堆空闲链表中也没有记录。

0:000> !heap 003a0000 -a

Index   Address  Name      Debugging options enabled

  5:   003a0000

    Segment at 003a0000 to 003b0000 (00003000 bytes committed)

    Flags:                00001002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00100000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000200

    DeCommit Total Thres: 00002000

    Total Free Size:      000001fd

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003a0608

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003a0050

    UCR FreeList:        003a0598

    FreeList Usage:      00000000 00000000 00000000 00000000

    FreeList[ 00 ] at 003a0178: 003a2020 . 003a2020 

        003a2018: 00108 . 00fe8 [10] - free

    Segment00 at 003a0640:

        Flags:           00000000

        Base:            003a0000

        First Entry:     003a0680

        Last Entry:      003b0000

        Total Pages:     00000010

        Total UnCommit:  0000000d

        Largest UnCommit:0000d000

        UnCommitted Ranges: (1)

            003a3000: 0000d000

 

    Heap entries for Segment00 in Heap 003a0000

        003a0000: 00000 . 00640 [01] - busy (640)

        003a0640: 00640 . 00040 [01] - busy (40)

        003a0680: 00040 . 01808 [01] - busy (1800)

        003a1e88: 01808 . 00088 [01] - busy (80)

        003a1f10: 00088 . 00108 [01] - busy (100)

        003a2018: 00108 . 00fe8 [10]

        003a3000:      0000d000      - uncommitted bytes.

 

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-07, 16:15 下午

这是第二次释放堆块,这里看出,和第一次一样堆没有释放,而且在堆空闲链表中也没有记录。

0:000> !heap 003a0000 -a

Index   Address  Name      Debugging options enabled

  5:   003a0000

    Segment at 003a0000 to 003b0000 (00003000 bytes committed)

    Flags:                00001002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00100000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000200

    DeCommit Total Thres: 00002000

    Total Free Size:      000001fd

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003a0608

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003a0050

    UCR FreeList:        003a0598

    FreeList Usage:      00000000 00000000 00000000 00000000

    FreeList[ 00 ] at 003a0178: 003a2020 . 003a2020 

        003a2018: 00108 . 00fe8 [10] - free

    Segment00 at 003a0640:

        Flags:           00000000

        Base:            003a0000

        First Entry:     003a0680

        Last Entry:      003b0000

        Total Pages:     00000010

        Total UnCommit:  0000000d

        Largest UnCommit:0000d000

        UnCommitted Ranges: (1)

            003a3000: 0000d000

 

    Heap entries for Segment00 in Heap 003a0000

        003a0000: 00000 . 00640 [01] - busy (640)

        003a0640: 00640 . 00040 [01] - busy (40)

        003a0680: 00040 . 01808 [01] - busy (1800)

        003a1e88: 01808 . 00088 [01] - busy (80)

        003a1f10: 00088 . 00108 [01] - busy (100)

        003a2018: 00108 . 00fe8 [10]

        003a3000:      0000d000      - uncommitted bytes.

 

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-07, 16:17 下午

在进行堆验证后,可以看到前2次堆块全部被释放了。这是为什么呢???

0:000> !heap 003a0000 -a

Index   Address  Name      Debugging options enabled

  5:   003a0000

    Segment at 003a0000 to 003b0000 (00003000 bytes committed)

    Flags:                00001002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00100000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000200

    DeCommit Total Thres: 00002000

    Total Free Size:      0000022f

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003a0608

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003a0050

    UCR FreeList:        003a0598

    FreeList Usage:      00000000 00000000 00000000 00000000

    FreeList[ 00 ] at 003a0178: 003a1e90 . 003a1e90 

        003a1e88: 01808 . 01178 [10] - free

    Segment00 at 003a0640:

        Flags:           00000000

        Base:            003a0000

        First Entry:     003a0680

        Last Entry:      003b0000

        Total Pages:     00000010

        Total UnCommit:  0000000d

        Largest UnCommit:0000d000

        UnCommitted Ranges: (1)

            003a3000: 0000d000

 

    Heap entries for Segment00 in Heap 003a0000

        003a0000: 00000 . 00640 [01] - busy (640)

        003a0640: 00640 . 00040 [01] - busy (40)

        003a0680: 00040 . 01808 [01] - busy (1800)

        003a1e88: 01808 . 01178 [10]

        003a3000:      0000d000      - uncommitted bytes.

 

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Thomson 2011-06-09, 20:13 下午
可能是被front-end (look aside list)给cache下来了,free的时候没没有真正的return 给heap back end.

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-10, 10:31 上午

但是,为什么在free list中也没有记录呢?还有为什么一检测堆,就会被释放掉了呢??

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


格蠹老雷 2011-06-11, 23:25 下午
确实如Tom所说,对于8-1024字节的小堆块,为了提高性能,在不启用调试机制的默认情况下,会先放到一个Look-aside列表中,这样比放到Free-List还要高效,不需要使用堆的全局锁
这个列表的头指针也记录在_HEAP结构中,但是公开的调试符号中没有包含这个字段

Re: 堆释放,在无标记时。New NtGlobalFlag contents: 0x00000000


Forward 2011-06-12, 19:17 下午

哦,谢谢Thomson,张老师。

在此对Thomson表示抱歉,我一开始没有认真琢磨,你的回复。

Powered by Community Server Powered by CnForums.Net