CreateThread会干扰VirtualAlloc的使用吗?

时间:2012-08-11 02:07:14

标签: c++ winapi virtual-memory

CreateThread分配的堆栈空间是否有可能干扰VirtualAlloc的使用?我找不到任何讨论或文档准确解释允许分配堆栈空间的位置......

以下更准确地说明了我的问题:

uint8_t *baseA = (uint8_t*)VirtualAlloc(NULL,1,MEM_RESERVE,PAGE_NOACCESS);

// Create a thread with the default stack size
HANDLE hThread = CreateThread(NULL,0,SomeThreadProc,NULL,NULL,NULL);

// Possibly create even more threads here.

// Can this ever fail in the absence of other allocators? It doesn't here...
uint8_t *baseB = (uint8_t*)VirtualAlloc(NULL,1,MEM_RESERVE,PAGE_NOACCESS);

// Furthermore, in this test, baseB-baseA == 65536 (unless the debugger did something),
// so nothing appeared between baseA and baseB... not even enough space for the
// full 64kb of wastage, as baseA points to 4096 bytes by itself

如果 实际上使用VirtualAlloc的某些模拟,有没有办法改变Windows在给定进程中分配堆栈空间的方式?

2 个答案:

答案 0 :(得分:3)

可以在进程的地址空间中的任何位置分配堆栈空间。现在没有关于此的文档,将来不太可能出现这样的文档。

您可以放心地假设线程和虚拟alloc的创建是独立的。如果不是这种情况,很多事情都会被打破。分配器不能给出重叠的地址范围。这是不可想象的。问题出在其他地方。

唯一可能看起来像关联的东西 - 使用的内存量和虚拟地址空间碎片。在这种情况下,最新的请求将失败。

我参与了内存分析工具。

enter image description here

此图显示了每个分配大小的虚拟分配数量的分布。

enter image description here

这是32位进程的地址空间内容示例(蓝色 - 已提交,洋红色 - 保留,绿色是可用内存)。

我在这里写的是基于真实的经验。

答案 1 :(得分:1)

Windows NT内核也以线程安全的方式处理高中断优先级的内存分配操作。

这意味着只有一个进程的一个线程可以同时分配内存,这使得所有分配进程都是线程安全的(理论上)。 堆栈分配和虚拟分配之间不应有任何干扰。

另外你应该保留在我的内容中,你可以分配1GB的空间,但你的程序仍然只使用它的2mb内存。

那是因为windows“预先分配”虚拟空间,但是在你使用它之前它不会分配(写在它上面)。

实际上内存管理有点复杂,但是现在你可以确保没有分配操作会干扰,因为Windows会将你的进程锁定到一个核心,延迟所有其他线程的alloc请求,只要处理分配。 (死锁)

*编辑:这也意味着如果分配数百万个小比特,分配和解除分配就是一个需要处理的性能。由于这种死锁行为,分配/取消分配更大的内存区域总是更好。