[英]a stack vs the stack and a heap vs the heap
我正在為我的數據組織決賽學習,我正在研究堆棧和堆,因為我知道它們將進入決賽,我將需要了解差異。 我知道堆棧是什么,堆是什么。
但是我對堆棧是什么和堆是什么感到困惑。
堆棧是 RAM 中存儲內存的地方,如果空間不足,就會發生堆棧溢出。 對象默認存儲在這里,當對象超出范圍時它會重新分配內存,並且速度更快。
堆是 RAM 中存儲內存的地方,如果空間不足,操作系統會分配更多空間。 對於要存儲在堆上的對象,需要使用 new 運算符來告知它,並且只有在告知后才會被釋放。 可能會出現碎片問題,它比堆棧慢,並且可以更好地處理大量內存。
但是什么是棧,什么是堆? 它是存儲內存的方式嗎? 例如靜態數組或靜態向量是堆棧類型和動態數組,鏈表是堆類型?
謝謝你們!
我不會進入虛擬內存(如果你願意,請閱讀相關內容)所以讓我們簡化一下,假設你有一定大小的 RAM。
您的代碼包含靜態初始化數據,還有一些靜態未初始化數據(C++ 中的靜態表示類似於全局變量)。 你有你的代碼。
當您編譯某些東西時,編譯器(和鏈接器)將按以下方式組織您的代碼並將其轉換為機器代碼(字節碼、1 和 0):
二進制文件(和目標文件)被組織成段(RAM 的一部分)。
首先你有DATA 段。 這是包含初始化變量值的段。 因此,如果您有變量,即int a=3, b = 4
它們將轉到 DATA 段(4 個字節的 RAM 包含 00000003h,其他 4 個字節包含 000000004h,十六進制表示法)。 它們是連續存儲的。
然后你有代碼段。 您的所有代碼都被翻譯成機器代碼(1 和 0)並連續存儲在此段中。
然后你有BSS 段。 有未初始化的全局變量(所有未初始化的靜態變量)。
然后你有STACK 段。 這是為堆棧保留的。 默認情況下,堆棧大小由操作系統決定。 你可以改變這個值,但我現在不會進入這個。 所有局部變量都放在這里。 當你調用某個函數時,首先func args被壓入堆棧,然后返回地址(退出函數時返回的位置),然后將一些計算機寄存器壓入這里,最后函數中聲明的所有局部變量都在堆棧上獲得保留空間.
你有HEAP 段。 這是 RAM 的一部分(大小也由操作系統決定),對象和數據使用 operator new
存儲在其中。
然后所有的段一個接一個地堆積起來,依次是DATA、CODE、BSS、STACK、HEAP。 還有一些其他段,但它們在這里並不重要,它們由操作系統加載到 RAM 中。 二進制文件還有一些頭文件,其中包含代碼從哪個位置(內存中的地址)開始的信息。
簡而言之,它們都是 RAM 的一部分,因為正在執行的所有內容都加載到 RAM 中(不能在 ROM(只讀)中,也不能在 HDD 中,因為 HDD 僅用於存儲文件。
當特別提到 C++ 的內存模型時,堆和堆棧指的是內存區域。 很容易將其與堆棧數據結構和堆數據結構混淆。 然而,它們是獨立的概念。
在討論編程語言時,堆棧內存被稱為“堆棧”,因為它的行為類似於堆棧數據結構。 堆有點用詞不當,因為它不一定(或可能)使用堆數據結構。 請參閱為什么兩個不同的概念都稱為“堆”? 討論為什么 C++ 的堆和數據結構的名稱相同,盡管是兩個不同的概念。
因此,要回答您的問題,這取決於上下文。 在編程語言和內存管理的上下文中,堆和堆棧是指具有特定屬性的內存區域。 否則,它們指的是特定的數據結構。
“堆棧”的技術定義是后進先出 (LIFO) 數據結構,其中數據被推入和拉出頂部。 就像現實世界中的一堆盤子一樣,你不會從中間或底部拉出一個,你[通常]不會從數據結構堆棧的中間或底部拉出數據。 當有關堆棧在編程方面的人會談,它往往(但不總是)是指硬件堆棧,這是由CPU堆棧指針寄存器控制。
就“堆”而言,就每個人都同意的定義而言,這通常變得更加模糊。 最好的定義可能是“大量空閑內存,從中分配空間用於動態內存管理”。 換句話說,當您需要新內存時,無論是用於數組還是使用 new 運算符創建的對象,它都來自操作系統為您的程序保留的堆。 這是程序 POV 中的“堆”,但只是操作系統 POV 中的“堆”。
您需要了解堆棧的重要一點是堆棧和函數/方法調用之間的關系。 每個函數調用都會在堆棧上保留空間,稱為堆棧幀。 該空間包含您的自動變量(在函數體內聲明的變量)。 當您退出函數時,堆棧幀和它包含的所有自動變量都會消失。
這種機制在使用的 CPU 資源方面非常便宜,但這些堆棧分配的變量的生命周期顯然受到函數范圍的限制。
另一方面,堆上的內存分配(對象)可以“永遠”存在,或者只要您需要它們,而無需考慮程序的控制流。 不利的一面是,由於您無法獲得這些堆分配對象的自動生命周期管理,因此您必須 1) 自己管理生命周期,或 2) 使用智能指針等特殊機制來管理這些對象的生命周期。 如果你弄錯了,你的程序會出現內存泄漏,或者訪問可能會意外更改的數據。
回復:關於堆棧與堆棧的問題:當您使用多個線程時,每個線程都有一個單獨的堆棧,以便每個線程可以獨立地流入和流出函數/方法。 大多數單線程程序只有一個堆棧:通用術語中的“堆棧”。
對於堆也是如此。 如果您有特殊需要,可以分配多個堆並在分配時選擇應該使用哪個堆。 這不太常見(而且是一個比我在這里提到的要復雜得多的話題。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.