[英]About C/C++ stack allocation
在學習C ++(和C)時,我對堆棧分配的工作有一些特別的疑問,我無法找到解決方案:
堆棧分配是否隱式調用malloc / free函數? 如果不; 它如何確保堆棧分配和堆分配之間沒有沖突?
如是; C ++中的堆棧分配是否也隱式調用new / delete? 如是; 重載一個類的new運算符會影響它的堆棧分配嗎?
它在VC ++中產生了令人困惑的結果; 但由於VC ++並不完全符合標准(或者我聽說過),我決定在這里問一下......
堆棧分配不使用malloc / free之類的東西。 它使用一段稱為程序堆棧的內存,它只是一段連續的內存。
有一個特殊的寄存器存儲堆棧的頂部。 當在堆棧上創建新對象時,頂部被抬起從而增加堆棧,當對象被解除分配(超出范圍)時,頂部被降低從而減少堆棧。
如果您嘗試在堆棧上分配太大的對象或者過於深入遞歸,則頂部將超出堆棧的最大允許大小,這稱為堆棧溢出。
注意:堆棧增長的實際方向(增加或減少地址) 將因系統而異 ,但無論實際方向如何,總體思路都是相同的。
第一個問題的答案是否。堆棧根本沒有從堆中分配。
您應該首先閱讀堆棧和堆的內容和位置以了解基本概念。
這里有一個很好的問題:
“它如何確保堆棧分配和堆分配之間沒有沖突?”
幾乎所有C / C ++實現中都有一個連續的地址空間,因此堆棧和堆分配的內存必須在該空間中共存。
雖然每次堆棧增長和收縮時都不會使用單個堆分配,但您仍然可以將堆棧視為從堆分配的單個大塊內存。 如果堆棧超出了該塊的邊界,那么我們就會有一個堆棧溢出(引人注目的名字......有人應該在它之后命名一個網站)。
在多線程程序中,每次線程啟動時,都必須為它分配一個新堆棧,當線程死亡時,可以釋放堆棧。 並且使用與通過malloc
/ free
公開的相同堆管理來分配整個堆棧塊是有意義的。
所以 - 非常接近 - 你可以認為堆棧是一種在堆中共存的對象。 當一個線程啟動時,整個堆棧都是malloc
-ed,然后它會從中進行子分配,然后一次性free
-d。
在Windows上,您可以(如果您喜歡危險地生活) 自己調用相同的虛擬內存API來查找堆棧並強制釋放其中的虛擬頁面。
在C和C ++中,存在兩種類型的內存分配“自動”,其中對象是在函數調用的生命周期中創建的,而“動態”則是由運行時提供的函數分配的。
在絕大多數運行時實現中,在創建線程時使用操作系統提供的連續堆棧分配自動對象。 堆棧通常從高值地址開始,並按對象的大小遞減。 動態分配(C中的malloc,C ++中的new)使用操作系統請求的其他一些內存。 由於操作系統知道堆棧正在使用的地址,因此它不會為動態請求分配相同的地址。 由於動態區域沒有排序,因此通常稱為堆。
所以'堆棧'分配不是malloc / free。 C ++中的自動對象調用構造函數和析構函數,但不是new或delete,因為new和delete也有管理動態內存的代碼。
不,堆棧分配不會調用malloc / free。 整個堆棧空間在程序開始時分配。 在進入每個函數時,堆棧指針足夠高,以允許堆棧上的空間為“堆棧幀”,這將是堆棧分配變量所在的位置。
Kepp記住“堆棧分配”是一個實現細節。 無法保證堆棧用於自動存儲。 例如,傳說中的IBM大型機沒有(雖然我被告知他們更現代的機器)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.