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在给定进程中分配堆栈空间的方式?
答案 0 :(得分:3)
可以在进程的地址空间中的任何位置分配堆栈空间。现在没有关于此的文档,将来不太可能出现这样的文档。
您可以放心地假设线程和虚拟alloc的创建是独立的。如果不是这种情况,很多事情都会被打破。分配器不能给出重叠的地址范围。这是不可想象的。问题出在其他地方。
唯一可能看起来像关联的东西 - 使用的内存量和虚拟地址空间碎片。在这种情况下,最新的请求将失败。
我参与了内存分析工具。
此图显示了每个分配大小的虚拟分配数量的分布。
这是32位进程的地址空间内容示例(蓝色 - 已提交,洋红色 - 保留,绿色是可用内存)。
我在这里写的是基于真实的经验。
答案 1 :(得分:1)
Windows NT内核也以线程安全的方式处理高中断优先级的内存分配操作。
这意味着只有一个进程的一个线程可以同时分配内存,这使得所有分配进程都是线程安全的(理论上)。 堆栈分配和虚拟分配之间不应有任何干扰。
另外你应该保留在我的内容中,你可以分配1GB的空间,但你的程序仍然只使用它的2mb内存。
那是因为windows“预先分配”虚拟空间,但是在你使用它之前它不会分配(写在它上面)。
实际上内存管理有点复杂,但是现在你可以确保没有分配操作会干扰,因为Windows会将你的进程锁定到一个核心,延迟所有其他线程的alloc请求,只要处理分配。 (死锁)
*编辑:这也意味着如果分配数百万个小比特,分配和解除分配就是一个需要处理的性能。由于这种死锁行为,分配/取消分配更大的内存区域总是更好。