2012-08-11 84 views
1

CreateThread分配的堆栈空间是否可能干扰VirtualAlloc的使用?我找不到在哪里堆栈空间允许被分配的精确解释任何讨论或文档...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如何在给定的进程中分配堆栈空间?

回答

3

堆栈空间可以分配到进程地址空间的任何地方。目前没有关于这方面的文件,将来也不太可能出现此类文件。

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

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

我从事内存分析工具。

enter image description here

此图为按照分配的大小的虚拟分配的数量的分布。

enter image description here

这是实施例的用于一个32位的进程的地址空间的内容(蓝 - 提交,品红 - 保留,绿色是一个免费的存储器)。

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

+1

+1这是不可想象的 - 操作系统在启动时会很快崩溃,甚至没有时间来蓝屏。 – 2012-08-11 05:20:05

+0

谢谢你的回答。也许“干涉”对于这个问题来说是一个严厉的话。我所要求的基本上是,如果'CreateThread',可以在任何地方分配堆栈空间 - 并且你回答了这个问题。通过“干涉”,我问是否可以将流程的虚拟地址空间分割出来(但是,现在我想到了它,还有什么地方可以分配它?)。所以,看起来好像随机线程分配会导致没有自定义分配器可以解析的碎片。 – defube 2012-08-11 05:58:38

+0

我喜欢我自己介绍的“AddrSpaceUtilization”概念。这是所有'VirtualAlloc'分配的大小总和与地址空间本身大小的比率。我在Windows上使用32位进程的经验表明,当此值小于85-90%时,所有工作都或多或少地正常。当它超过90%时,出现各种问题。 – 2012-08-11 06:46:33

1

windows NT内核以高优先级中断来处理内存分配操作,同样也是以线程安全的方式进行的。

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

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

这是因为Windows“预先分配”了虚拟空间,但它不会分配它,直到您使用它(写入它)。

实际上,内存管理是非常复杂的,但现在你可以放心,没有分配操作应该干涉,因为windows将你的进程锁定到一个核心,延迟所有其他线程分配请求,只要分配是处理。 (死锁)

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