1

分配的堆栈空间是否可能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 在给定进程中分配堆栈空间的方式?

4

2 回答 2

3

堆栈空间可以分配在进程地址空间的任何位置。现在没有这方面的文档,而且此类文档不太可能在未来出现。

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

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

我从事内存分析实用程序。

在此处输入图像描述

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

在此处输入图像描述

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

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

于 2012-08-11T02:37:56.703 回答
1

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

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

此外,您应该记住您可以分配 1GB 的空间,但您的程序仍然只使用它的 2mb RAM。

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

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

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

于 2012-08-11T02:28:47.773 回答