首頁/ 汽車/ 正文

還有多少人搞不懂堆記憶體和棧記憶體的區別?

這篇文章分享一個面試中經常被問到的知識點:堆記憶體和棧記憶體有什麼區別?平時開發應該使用堆記憶體還是棧記憶體?

要回答這個問題,我們首先需要知道什麼是堆記憶體,什麼是棧記憶體,它們的分配和回收有什麼特點?

先介紹下棧記憶體:

棧記憶體是為執行緒留出的臨時空間,每個執行緒都有一個固定大小的棧空間,而且棧空間儲存的資料只能由當前執行緒訪問,所以它是執行緒安全的。

棧空間的分配和回收是由系統來做的,我們不需要手動控制。

當一個函式呼叫時,系統就會為該函式的呼叫分配棧空間,當函式返回後,系統就會自動回收這塊空間,同理,下次其它函式呼叫和返回,系統還是會自動分配和回收空間。

那它是怎麼分配和回收的呢?

可以看這兩個動畫

還有多少人搞不懂堆記憶體和棧記憶體的區別?

還有多少人搞不懂堆記憶體和棧記憶體的區別?

棧空間的大小是固定的,它有一個水位線,標識棧空間的分配狀態,水位線裡面的表示已經分配,然後這個水位線會根據函式呼叫和返回的情況自動調整。

這裡可以看到,棧空間的分配和回收非常簡單,只需要調整水位線位置就可以了,沒有任何多餘操作。

那堆記憶體呢?

我們平時在C語言和C++中使用malloc和new分配的記憶體就是堆記憶體,堆記憶體的一大特點就是大小不固定,可以動態擴容,空間由程式設計師動態分配,更加靈活。

然而,既然有優點也必然伴隨著缺點。

第一個缺點就是它容易產生記憶體洩露,malloc出來的沒有free,new出來的如果沒有delete,都會產生記憶體洩露,真正專案記憶體洩露產生的情況肯定比這個複雜的多。

第二個缺點,容易產生記憶體碎片,在分配和回收時需要對很多記憶體碎片進行整理,效率較低,具體可以看這個動畫。

還有多少人搞不懂堆記憶體和棧記憶體的區別?

所以才會有很多自定義的記憶體分配器,但它肯定還是沒有棧空間分配回收速度快。

第三個缺點,執行緒不安全,它不像棧記憶體是執行緒獨立的,堆記憶體可以被一個程序內所有的執行緒訪問,多執行緒操作就容易產生問題,很多奇奇怪怪的操作就是這麼引起的。

相關影片推薦

90分鐘瞭解Linux記憶體架構,numa的優勢,slab的實現,vmalloc的原理

linux記憶體管理-龐雜的記憶體問題,如何理出自己的思路出來

學習地址:C/C++Linux伺服器開發/後臺架構師【零聲教育】-學習影片教程-騰訊課堂

需要C/C++ Linux伺服器架構師學習資料加qun

812855908

獲取(資料包括

C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg

等),免費分享

還有多少人搞不懂堆記憶體和棧記憶體的區別?

那什麼變數儲存在棧上,什麼儲存在堆上呢?普通的A a,這種就是都儲存在棧上,當使用new和malloc分配的空間會儲存在堆上,看這個圖:

還有多少人搞不懂堆記憶體和棧記憶體的區別?

new出來的實際空間是在堆上分配,然後在棧上開闢一個指標大小的空間,這個空間有一個指標,指向堆上的那塊記憶體,這樣給變數和堆記憶體之間就關聯起來了。

那什麼情況下使用棧記憶體,什麼情況下使用堆記憶體呢?

我整理出來了一個表,貼在這裡:

速度

空間管理

高效,不會產生碎片

會產生記憶體碎片

訪問許可權

只能區域性變數

可以訪問全域性變數

空間大小限制

作業系統限制

沒有特定的限制

記憶體分配

連續

隨機分配

分配和釋放

編譯器指令自動管理

程式設計師手動管理

開銷

主要問題

空間小

記憶體碎片

靈活性

固定大小

可以resize

這裡可以根據實際需求來決定使用哪類記憶體。

當然,其實也不用關注那麼多,我一般就是大記憶體使用堆,區域性變數小記憶體使用棧。

這裡還涉及到很多其它知識點,比如程序的記憶體空間佈局是怎麼樣的,棧空間會不會汙染、堆記憶體具體是怎麼分配和回收的。

最後是

提問環節

,大家可以在評論區討論一下哈。

當定義一個vector a(100); a在哪塊記憶體?那100a的空間又在哪裡?

當定義一個array a; a在哪塊記憶體,那100個a的空間又在哪裡?

相關文章

頂部