elv*_*ear 0 c++ winapi memory-management virtualalloc virtualquery
我试图在 Windows 应用程序中加载的 DLL 中的某个内存范围内分配一定数量的内存。
我这样做的方式是使用VirtualQuery()
搜索标记为空闲且在我需要进行分配的边界内的内存区域。我看到的是,即使该区域被标记为MEM_FREE
VirtualAlloc()
失败,有时也无法分配内存。
该代码非常接近以下内容:
LPVOID address = NULL, mem = NULL;
for (address = LOWER_RANGE; address < UPPER_RANGE;) {
MEMORY_BASIC_INFORMATION mbi = {0};
if (VirtualQuery(address, &mbi, sizeof(mbi))) {
if (mbi.State == MEM_FREE && mbi.RegionSize >= ALLOC_SIZE) {
mem = VirtualAlloc(address, ALLOC_SIZE,
MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READ);
if (mem) {
break;
}
}
}
address = mbi.BaseAddress + mbi.RegionSize;
}
Run Code Online (Sandbox Code Playgroud)
当VirtualAlloc()
失败时,GetLastError()
返回ERROR_INVALID_ADDRESS
(487).
我解决它的方法是,如果它足够大,则mbi.RegionSize
使用页面大小步骤扫描以查找允许我分配所需内存的地址。
为什么根据VirtualQuery
整个区域应该是空闲的并且我应该能够在我想要的任何地址内分配,但是通常当第一个VirtualAlloc
失败时我必须循环几个步骤直到它最终成功。
当您向 VirtualAlloc 提供地址并使用 MEM_RESERVE 标志时,地址将向下舍入到最接近的分配粒度 (64K) 倍数。您可能会发现空闲页面区域位于未完全保留的已分配 64K 块中。在分配块中的所有页面都被释放之前,无法分配(或保留)这些块中的未保留页面。
来自VirtualAlloc 的MSDN 文档:
lpAddress [输入,可选]
要分配的区域的起始地址。如果正在保留内存,则指定的地址将向下舍入到最接近的分配粒度倍数。[...] 要确定主机上的页面大小和分配粒度,请使用 GetSystemInfo函数。
归档时间: |
|
查看次数: |
1163 次 |
最近记录: |