VirtualAlloc对齐方式是否与分配大小一致?

ran*_*cts 4 winapi virtual-memory

使用VirtualAllocAPI分配和提交具有两个页面边界大小的幂的虚拟内存区域时,例如:

void* address = VirtualAlloc(0, 0x10000, MEM_COMMIT, PAGE_READWRITE); // Get 64KB
Run Code Online (Sandbox Code Playgroud)

address似乎永远在64KB对齐,而不仅仅是页面边界,这在我的情况是4KB。

问题是:这种一致性是可靠和明确的,还是偶然的? 文档指出,它保证在页面边界上,但是没有解决我所看到的问题。我问是因为稍后我想获取一个任意指针(由使用此块的池分配器提供),并通过类似于以下内容的方法确定它属于哪个64KB块:

void* chunk = (void*)((uintptr_t)ptr & 0xFFFF0000);
Run Code Online (Sandbox Code Playgroud)

IIn*_*ble 6

该文档VirtualAlloc描述了2种情况的行为:1)保留内存和2)提交内存:

如果要保留内存,则将指定的地址四舍五入到分配粒度的最接近倍数。

如果内存已被保留并正在提交,则地址将向下舍入到下一页边界

换句话说,以分配粒度的倍数分配(保留)内存,并以页面大小的倍数提交内存。如果要在单个步骤中保留和提交内存,则将按照分配粒度的倍数对齐它。提交已经保留的内存时,它将在页面边界对齐。

要查询系统的页面大小和分配粒度,请调用GetSystemInfo。该SYSTEM_INFO结构是dwPageSizedwAllocationGranularity将举行的页面大小和分配粒度,分别。


Han*_*ant 5

这是完全正常的。SYSTEM_INFO.dwAllocationGranularity的值为64KB。这是一种防止地址空间碎片的简单对策,4KB页面太小。如果您更改块中单个页面的页面保护,则内存管理器仍会根据需要细分64KB的块。

使用HeapAlloc()进行子分配。堆管理器具有针对碎片的特定对策。

  • 是的,分配不是粒度倍数的大小会浪费地址空间。这不是一个很大的问题,它是虚拟的,并且有很多。自己使用VirtualAlloc并不是一个好主意,最好让它交给HeapAlloc和朋友。 (2认同)