【问题标题】:Given a pointer, find the heap block where it resides给定一个指针,找到它所在的堆块
【发布时间】:2015-11-23 07:27:14
【问题描述】:

一个例子:

char *p1 = HeapAlloc(GetProcessHeap(), 0, 12); // returns 0x1234
char *p2 = p1 + 7;

// ...

void *p;
size_t size;
if(GetHeapBlock(p2, &p, &size))
    printf("%p (%zd)", p, size); // should print "0x1234 (12)"

如何实现上面的GetHeapBlock函数?

我查看了Proc Heap ViewerHeapMemView 程序,但它们显示的信息并不完全符合我的预期。例如指针有时较低,尺寸较大,因此对于上面的示例,它们可以显示大小为 256 的 0x1200。此外,两者都显示不同的信息。

一般来说,我可以调用GetProcessHeaps,并为每个指针调用HeapValidate,从输入变低开始。然后我可以打电话给HeapSize。但这听起来效率极低。有没有更好的解决方案?

附:我需要这个用于诊断,而不是用于生产,因此不是 100% 可靠/高性能的解决方案是可以接受的。

【问题讨论】:

    标签: c windows winapi heap-memory


    【解决方案1】:

    如何使用HeapWalk,并像这样遍历您的进程堆:

    HANDLE hHeap = GetProcessHeap();
    char *p1 = (char*)HeapAlloc(hHeap, 0, 12);
    cout << "P1: " << static_cast<void*>(p1) << endl;
    char *p2 = p1 + 7;
    
    PROCESS_HEAP_ENTRY entry;
    entry.lpData = NULL;
    
    BYTE regionIndex = 0xFF;
    
    bool found = false;
    while (!found && HeapWalk(hHeap, &entry) != FALSE)
    {
        if ((entry.wFlags & PROCESS_HEAP_REGION) != 0)
        {
            if (p2 < entry.Region.lpLastBlock && p2 >= entry.Region.lpFirstBlock)
            {
                cout << "Heap Region" << endl;
                cout << "First Block: " << entry.Region.lpFirstBlock << endl;
                cout << "Overhead: " << entry.cbOverhead << endl;
                cout << "Size: " << entry.cbData << endl;
                cout << "Data: " << entry.lpData << endl;
                regionIndex = entry.iRegionIndex;
            }
            else
            {
                // should work to skip to the last block in the region.  YMMV. Didn't test this scenario.
                entry.lpData = entry.Region.lpLastBlock;
            }
    
        }
        else if ((entry.wFlags & (PROCESS_HEAP_ENTRY_BUSY | PROCESS_HEAP_ENTRY_MOVEABLE)) != 0)
        {
            if (entry.iRegionIndex == regionIndex)
            {
                if (p2 >= entry.lpData && p2 < ((char*)entry.lpData + entry.cbData))
                {
                    cout << "Heap Block" << endl;
                    cout << "Heap Data: " << entry.lpData << endl;
                    cout << "Block hMem: " << entry.Block.hMem << endl;
                    cout << "Block Size: " << (int)entry.cbData << endl;
                    cout << "Overhead: " << (int)entry.cbOverhead << endl;
                    found = true;
                }
            }
        }
    }
    

    从技术上讲,这个示例是 C++,但即使对于纯 C,这个想法也是一样的。(我只是懒惰,我已经有一个 C++ 临时程序,std::cout 很方便。)基本上你初始化一个PROCESS_HEAP_ENTRY将其 lpData 设置为 NULL 的结构,以在堆的开头开始遍历。有关详细信息,请参阅 MSDN HeapWalk() 文章。

    当我在我的系统上运行它时,我得到:

    P1: 00379FC0
    Heap Region
    First Block: 00360598
    Overhead:
    Size: 1416
    Data: 00360000
    Heap Block
    Heap Data: 00379FC0
    Block hMem: 0001A000
    Block Size: 12
    Overhead: 28
    

    编辑添加:您也可以使用此方法转储整个进程堆。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-08
      相关资源
      最近更新 更多