2012-09-15 46 views
4

我對某個exe堆棧的位置感到有點困惑。我知道程序運行前,CRT通過分配一定數量的堆(它由分配頁面的操作系統分配)來初始化堆,但堆棧在哪裏?它是否也在一個頁面上?或者它是由用戶模式(ring3)中的所有程序通過在GDT上使用ring3描述符共享的(我認爲不是,但我不確定)?Windows上的堆棧 - 它在哪裏?

回答

5

Windows將爲每個線程保留一個連續的虛擬內存區域(默認爲1MB)。然後,它提交該內存區域的幾個最頂層頁面,並將其標記爲守護頁之下的一對。隨着線程的堆棧向下增長,如果訪問防護頁面,則會發生異常,並且Windows會提交防護頁面並將其標記爲守衛。

您可以使用出色的SysInternals實用程序VMMap探索此行爲。下面是該工具的代碼段:

enter image description here

3

每個線程都有自己的堆棧。這只是爲此目的分配的一塊內存。

所有內存中的頁面分配,包括堆棧(在Windows上,我相信堆棧默認爲1MB,所以它會跨越多個頁面,因爲大多數內存頁是4KB。)

但它的真的只是堆棧指針寄存器指向的一塊內存。

+0

獲得創建線程時,因此對於單線程應用中,當應用程序啓動時創建的主線程的堆棧堆棧初始化時,應該這也是由crt完成? –

+0

crt無法做到 - 它可能不是C程序!即使是這樣,堆棧必須在crt運行之前設置,否則crt將無法使用堆棧,即。它將無法使用任何自動變量,參數或進行任何函數調用。 Windows操作系統加載器設置初始堆棧,由EXE/DLL/SYS /任何PE頭中的數據指示。 –

1

Windows中的每個程序都是一個進程。過程通常不會在彼此之間分享他們的回憶。

共享和不共享是每個進程的虛擬地址空間如何映射到物理內存的問題。

如果兩個進程將其地址空間的一部分映射到物理內存的相同頁面上,那麼這些內存就會被它們有效地共享,並且每個進程都可以讀取並可能寫入它並觀察其他進程的寫入。

共享堆棧內存沒有意義,所以每個進程都有自己的堆棧。實際上,流程更像容器。執行代碼並使用堆棧的實體是線程。每個過程至少有一個線程。線程有自己的堆棧,但由於進程的線程位於相同的虛擬地址空間,因此它們可以訪問其他堆棧。有時在線程之間共享堆棧數據很有用,但應該小心謹慎,以免破壞線程狀態並導致掛起或崩潰。

相關問題