2012-08-11 127 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將你的進程鎖定到一個核心,延遲所有其他線程分配請求,只要分配是處理。 (死鎖)

*編輯:這也意味着分配和解除分配是一種性能需要過程,如果你分配數百萬的小比特。由於這種死鎖行爲,分配/取消分配更大的內存區域總是更好。