複製鏈接
請複製以下鏈接發送給好友

HeapCreate

鎖定
HeapCreate,計算機函數語言,指的是進程中創建輔助堆棧。
外文名
Heapcreate
所屬學科
計算機

目錄

HeapCreate概論:

你可以在進程中創建輔助堆棧,方法是讓線程調用HeapCreate( );函數:
HANDLE WINAPI HeapCreate(
__in DWORD flOptions,
__in SIZE_T dwInitialSize,
__in SIZE_T dwMaximumSize );
第一個參數flOptions用於修改如何在堆棧上執行各種操作。你可以設定0、HEAP_NO_SERIALIZE、HEAP_GENERATE_EXCEPTIONS、HEAP_CREATE_ENABLE_EXECUTE或者是這些標誌的組合。
HEAP_NO_SERIALIZE:對堆的訪問是非獨佔的,如果一個線程沒有完成對堆的操作,其它線程也可以進程堆操作,這個開關是非常危險的,應儘量避免使用。
HEAP_GENERATE_EXCEPTIONS:當堆分配內存失敗時,會拋出異常。如果不設置,則返回NULL。
HEAP_CREATE_ENALBE_EXECUTE:堆中存放的內容是可以執行的代碼。如果不設置,意味着堆中存放的是不可執行的數據。 [1] 
按照默認設置,堆棧將順序訪問它自己,這樣,多個線程就能夠分配和釋放堆棧中的內存
塊而不至於破壞堆棧。

HeapCreate具體操作

當試圖從堆棧分配一個內存塊時, HeapAlloc函數(下面將要介紹)必
須執行下列操作:
1、遍歷分配的和釋放的內存塊的鏈接表。
2、尋找一個空閒內存塊的地址。
3、通過將空閒內存塊標記為“已分配”分配新內存塊。
4、將新內存塊添加給內存塊鏈接表。
下面這個例子説明為什麼應該避免使用HEAPNOSERIALIZE標誌。假定有兩個線程
圖同時從同一個堆棧中分配內存塊。線程1執行上面的第一步和第二步,獲得了空閒內存塊的
地址。但是,在該線程可以執行第三步之前,它的運行被線程2搶佔,線程2得到一個機會來
執行上面的第一步和第二步。由於線程1尚未執行第三步,因此線程2發現了同一個空閒內存塊
的地址。
由於這兩個線程都發現了堆棧中它們認為是空閒的內存塊,因此線程1更新了鏈接表,給
新內存塊做上了“已分配”的標記。然後線程2也更新了鏈接表,給同一個內存塊做上了“已
分配”標記。兩個線程暫時都沒有發現問題,但是兩個線程得到的是完全相同的內存
塊的地址。
這種類型的錯誤是很難跟蹤的,因為它不會立即表現出來。相反,這個錯誤會在後台等待
着,直到很不適合的時候才顯示出來。可能出現的問題是:
· 內存塊的鏈接表已經被破壞。在試圖分配或釋放內存塊之前,這個問題不會被發現。
· 兩個線程共享同一個內存塊。線程1和線程2會將信息寫入同一個內存塊。當線程1查看該
內存塊的內容時,它將無法識別線程2提供的數據。
· 一個線程可能繼續使用該內存塊並且將它釋放,導致另一個線程改寫未分配的內存。這
將破壞該堆棧。
解決這個問題的辦法是讓單個線程獨佔對堆棧和它的鏈接表的訪問權,直到該線程執行了
對堆棧的全部必要的操作。如果不使用H E A P _ N O _ S E R I A L I Z E標誌,就能夠達到這個目的。
只有當你的進程具備下面的一個或多個條件時,才能安全地使用H E A P N O S E R I A L I Z E標誌:
· 你的進程只使用一個線程。
· 你的進程使用多個線程,但是隻有單個線程訪問該堆棧
· 你的進程使用多個線程,但是它設法使用其他形式的互斥機制,如關鍵代碼段、互斥對
象和信標(第8、9章中介紹),以便設法自己訪問堆棧。
如果對是否可以使用H E A P N O S E R I A L I Z E標誌沒有把握,那麼請不要使用它。如果不
使用該標誌,每當調用堆棧函數時,線程的運行速度會受到一定的影響,但是不會破壞你的堆
棧及其數據。
另一個標誌H E A P G E N E R AT E E X C E P T I O N S,會在分配或重新分配堆棧中的內存塊的嘗
試失敗時,導致系統引發一個異常條件。所謂異常條件,只不過是系統使用的另一種方法,以
便將已經出現錯誤的情況通知你的應用程序。有時在設計應用程序時讓它查看異常條件比查看
返回值要更加容易些。異常條件將在第2 3、2 4和2 5章中介紹。
H e a p C r e a t e的第二個參數d w I n i t i a l S i z e用於指明最初提交給堆棧的字節數。如果必要的話,
H e a p C r e a t e函數會將這個值將向上取整為C P U頁面大小的倍數。最後一個參數d w M a x i m u m S i z e用於指明堆棧能夠擴展到的最大值(即系統能夠為堆棧保留的地址空間的最大數量)。如果
d w M a x i m u m S i z e大於0,那麼你創建的堆棧將具有最大值。如果嘗試分配的內存塊會導致堆棧
超過其最大值,那麼這種嘗試就會失敗。
如果d w M a x i m u m S i z e的值是0,那麼可以創建一個能夠擴展的堆棧,它沒有內在的限制。
從堆棧中分配內存塊只需要使堆棧不斷擴展,直到物理存儲器用完為止。如果堆棧創建成功,
H e a p C r e a t e函數返回一個句柄以標識新堆棧。該句柄可以被其他堆棧函數使用。
若要從堆棧中分配內存塊,只需要調用H e a p A l l o c函數
參考資料
  • 1.    Jeffrey Richter.Windows 核心編程:微軟,2008:495