這篇文章分享一個面試中經常被問到的知識點:堆記憶體和棧記憶體有什麼區別?平時開發應該使用堆記憶體還是棧記憶體?
要回答這個問題,我們首先需要知道什麼是堆記憶體,什麼是棧記憶體,它們的分配和回收有什麼特點?
先介紹下棧記憶體:
棧記憶體是為執行緒留出的臨時空間,每個執行緒都有一個固定大小的棧空間,而且棧空間儲存的資料只能由當前執行緒訪問,所以它是執行緒安全的。
棧空間的分配和回收是由系統來做的,我們不需要手動控制。
當一個函式呼叫時,系統就會為該函式的呼叫分配棧空間,當函式返回後,系統就會自動回收這塊空間,同理,下次其它函式呼叫和返回,系統還是會自動分配和回收空間。
那它是怎麼分配和回收的呢?
可以看這兩個動畫
棧空間的大小是固定的,它有一個水位線,標識棧空間的分配狀態,水位線裡面的表示已經分配,然後這個水位線會根據函式呼叫和返回的情況自動調整。
這裡可以看到,棧空間的分配和回收非常簡單,只需要調整水位線位置就可以了,沒有任何多餘操作。
那堆記憶體呢?
我們平時在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
當定義一個array