簡體   English   中英

堆棧與堆棧和堆與堆

[英]a stack vs the stack and a heap vs the heap

我正在為我的數據組織決賽學習,我正在研究堆棧和堆,因為我知道它們將進入決賽,我將需要了解差異。 我知道堆棧是什么,堆是什么。

但是我對堆棧是什么和堆是什么感到困惑。

堆棧是 RAM 中存儲內存的地方,如果空間不足,就會發生堆棧溢出。 對象默認存儲在這里,當對象超出范圍時它會重新分配內存,並且速度更快。

堆是 RAM 中存儲內存的地方,如果空間不足,操作系統會分配更多空間。 對於要存儲在堆上的對象,需要使用 new 運算符來告知它,並且只有在告知后才會被釋放。 可能會出現碎片問題,它比堆棧慢,並且可以更好地處理大量內存。

但是什么是棧,什么是堆? 它是存儲內存的方式嗎? 例如靜態數組或靜態向量是堆棧類型和動態數組,鏈表是堆類型?

謝謝你們!

“堆棧”和“堆”是程序或操作系統以特定方式使用的內存塊。 例如,調用堆棧可以保存與函數調用有關的數據, 而堆是專門用於動態分配空間的內存區域。

將它們與堆棧和堆數據結構進行對比。

堆棧可以被認為是一個數組,其中最后一個元素將是第一個元素。 對此的操作稱為 push 和 pop。

是一種數據結構,表示一種特殊類型的圖,其中每個節點的值都大於節點子節點的值。

附帶說明一下,請記住,“堆棧”或“堆”或任何堆棧/堆數據結構對於任何給定的編程語言都是獨一無二的,而只是計算機科學領域中的概念。

我不會進入虛擬內存(如果你願意,請閱讀相關內容)所以讓我們簡化一下,假設你有一定大小的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM