问题
I'm using C++ on Windows under Visual Studio 2012.
I have a start and end memory address and need to generate a list of page base addresses/handles between the two addresses. I considered the possibility of probing the pages manually but thought there must be a better way to enumerate them.
Does such a way exist?
Disclaimer; The final page handles must be the base address such that when the size of a windows page is added to them the resulting address does not overlap into the next page. The preferred solution would not be platform specific and be compatible with 32-bit with/without WOW64.
回答1:
VirtualQuery is pretty much your only option. It should be fairly efficient:
The function determines the attributes of the first page in the region and then scans subsequent pages until it scans the entire range of pages or until it encounters a page with a nonmatching set of attributes.
So you'd start by calling it at the beginning of the range that you care about, and you'd get back a single chunk of pages. The next call would start right after that chunk, and the next one after that, and so on.
Here's a completely untested function that would populate an array of MEMORY_BASIC_INFORMATION structures:
int EnumVirtualAllocations(const void* ptr, size_t length, MEMORY_BASIC_INFORMATION* info, int size)
{
const void* end = (const void*)((const char*)ptr + length);
int index = 0;
while (index < size && ptr < end &&
VirtualQuery(ptr, &info[index], sizeof(*info)) == sizeof(*info))
{
MEMORY_BASIC_INFORMATION* i = &info[index];
if (i->State != MEM_FREE) index++;
ptr = (const void*)((const char*)(i->BaseAddress) + i->RegionSize);
}
return index;
}
来源:https://stackoverflow.com/questions/15018376/enumerate-the-pages-in-a-memory-range