1. 還有多少人搞不懂堆內(nèi)存和棧內(nèi)存的區(qū)別?

        共 1654字,需瀏覽 4分鐘

         ·

        2022-06-08 00:46

        大家好,我是魚皮。

        今天分享一個(gè)面試中經(jīng)常被問到的知識點(diǎn):堆內(nèi)存和棧內(nèi)存有什么區(qū)別?平時(shí)開發(fā)應(yīng)該使用堆內(nèi)存還是棧內(nèi)存?

        要回答這個(gè)問題,我們首先需要知道什么是堆內(nèi)存,什么是棧內(nèi)存,它們的分配和回收有什么特點(diǎn)??



        先介紹下棧內(nèi)存:


        棧內(nèi)存是為線程留出的臨時(shí)空間,每個(gè)線程都有一個(gè)固定大小的??臻g,而且??臻g存儲的數(shù)據(jù)只能由當(dāng)前線程訪問,所以它是線程安全的。


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


        當(dāng)一個(gè)函數(shù)調(diào)用時(shí),系統(tǒng)就會為該函數(shù)的調(diào)用分配棧空間,當(dāng)函數(shù)返回后,系統(tǒng)就會自動回收這塊空間,同理,下次其它函數(shù)調(diào)用和返回,系統(tǒng)還是會自動分配和回收空間。


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


        可以看這兩個(gè)動畫





        棧空間的大小是固定的,它有一個(gè)水位線,標(biāo)識??臻g的分配狀態(tài),水位線里面的表示已經(jīng)分配,然后這個(gè)水位線會根據(jù)函數(shù)調(diào)用和返回的情況自動調(diào)整。


        這里可以看到,??臻g的分配和回收非常簡單,只需要調(diào)整水位線位置就可以了,沒有任何多余操作。




        那堆內(nèi)存呢?


        我們平時(shí)在C語言和C++中使用malloc和new分配的內(nèi)存就是堆內(nèi)存,堆內(nèi)存的一大特點(diǎn)就是大小不固定,可以動態(tài)擴(kuò)容,空間由程序員動態(tài)分配,更加靈活。


        然而,既然有優(yōu)點(diǎn)也必然伴隨著缺點(diǎn)。


        第一個(gè)缺點(diǎn)就是它容易產(chǎn)生內(nèi)存泄露,malloc出來的沒有free,new出來的如果沒有delete,都會產(chǎn)生內(nèi)存泄露,真正項(xiàng)目內(nèi)存泄露產(chǎn)生的情況肯定比這個(gè)復(fù)雜的多。


        第二個(gè)缺點(diǎn),容易產(chǎn)生內(nèi)存碎片,在分配和回收時(shí)需要對很多內(nèi)存碎片進(jìn)行整理,效率較低,具體可以看這個(gè)動畫。



        所以才會有很多自定義的內(nèi)存分配器,但它肯定還是沒有??臻g分配回收速度快。


        第三個(gè)缺點(diǎn),線程不安全,它不像棧內(nèi)存是線程獨(dú)立的,堆內(nèi)存可以被一個(gè)進(jìn)程內(nèi)所有的線程訪問,多線程操作就容易產(chǎn)生問題,很多奇奇怪怪的操作就是這么引起的。




        那什么變量存儲在棧上,什么存儲在堆上呢?普通的A a,這種就是都存儲在棧上,當(dāng)使用new和malloc分配的空間會存儲在堆上,看這個(gè)圖:

        new出來的實(shí)際空間是在堆上分配,然后在棧上開辟一個(gè)指針大小的空間,這個(gè)空間有一個(gè)指針,指向堆上的那塊內(nèi)存,這樣給變量和堆內(nèi)存之間就關(guān)聯(lián)起來了。




        那什么情況下使用棧內(nèi)存,什么情況下使用堆內(nèi)存呢?


        我整理出來了一個(gè)表,貼在這里:



        速度
        空間管理高效,不會產(chǎn)生碎片會產(chǎn)生內(nèi)存碎片
        訪問權(quán)限只能局部變量可以訪問全局變量
        空間大小限制操作系統(tǒng)限制沒有特定的限制
        內(nèi)存分配連續(xù)隨機(jī)分配
        分配和釋放編譯器指令自動管理程序員手動管理
        開銷
        主要問題空間小內(nèi)存碎片
        靈活性固定大小可以resize


        這里可以根據(jù)實(shí)際需求來決定使用哪類內(nèi)存。


        當(dāng)然,其實(shí)也不用關(guān)注那么多,我一般就是大內(nèi)存使用堆,局部變量小內(nèi)存使用棧。


        這里還涉及到很多其它知識點(diǎn),比如進(jìn)程的內(nèi)存空間布局是怎么樣的,??臻g會不會污染、堆內(nèi)存具體是怎么分配和回收的。


        最后是提問環(huán)節(jié),大家可以在評論區(qū)討論一下哈。


        • 當(dāng)定義一個(gè)vector a(100);?a在哪塊內(nèi)存?那100a的空間又在哪里?

        • 當(dāng)定義一個(gè)array a; a在哪塊內(nèi)存,那100個(gè)a的空間又在哪里?




        參考鏈接

        https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

        https://www.guru99.com/stack-vs-heap.html

        https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/

        最后,歡迎加入?魚皮的編程知識星球(點(diǎn)擊了解詳情),和 8200 多名小伙伴們一起交流學(xué)習(xí),向魚皮和大廠同學(xué) 1 對 1 提問、幫你制定學(xué)習(xí)計(jì)劃不迷茫、跟著魚皮直播做項(xiàng)目(往期項(xiàng)目可無限回看)領(lǐng)取魚皮原創(chuàng)編程學(xué)習(xí)/求職資料等。


        往期推薦

        幾個(gè)對程序員的誤解,害人不淺!

        編程導(dǎo)航,火了!

        Gitee 很無奈!

        我的 IP 歸屬地,是咋被挖出來的?

        我造了個(gè)輪子,完整開源!



        瀏覽 25
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 国产美女视频黄 | 日本无码加勒比一区二区 | 欧美色涩在线第一页 | 加勒比一本无码AV | 亚洲视频无码在线 |