Reputation: 6911
An example:
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)"
How can I implement the GetHeapBlock
function above?
I looked at the Proc Heap Viewer, HeapMemView programs, but the information that they display is not exactly what I expect. e.g. the pointers are sometimes lower, and the sizes are larger, so for the example above they could show 0x1200 of size 256. Also, both show different information.
In general, I could call GetProcessHeaps
, and for each heap call HeapValidate
for every pointer, starting from the input getting lower. Then I could call HeapSize
. But this sounds extremely inefficient. Is there a better solution?
P.S. I need this for diagnostics, not for production, so a solution which is not 100% reliable/performant is acceptable.
Upvotes: 0
Views: 370
Reputation: 6738
How about using HeapWalk
, and walking your process heap like this:
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;
}
}
}
}
Technically this sample is C++, but the idea remains the same even for pure C. (I'm just lazy and I already had a C++ scratch program, and std::cout
is convenient.) Basically you initialize a PROCESS_HEAP_ENTRY
structure with it's lpData
set to NULL, to start the walk at the beginning of the heap. See the MSDN HeapWalk()
article for more information.
When I run this on my system I get:
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
Edited to add: You could also use this method to dump the entire process heap.
Upvotes: 1