日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内存分配方式以及堆和栈的区别

發布時間:2023/12/15 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内存分配方式以及堆和栈的区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載:https://blog.csdn.net/shanchangyi/article/details/51854795

對于一個程序要運行,涉及到的內存分配是一個首要問題,這里簡單說一下一個簡單的程序運行所涉及到的內存分配方式。另外,在數據結構中存在堆和棧的概念,棧是一種先進后出的數據結構,堆則是一種排序方式,而在內存分配中也存在堆(heap)和棧(stack)的概念,與數據結構中的概念不同,這里簡單說明在內存分配中的堆棧之間的不同。

一、內存分配方式

1、全局變量和靜態變量(static變量),是由編譯器自動分配和釋放的,初始化的全局變量和靜態變量放在同一塊內存區中,未初始化的全局變量和靜態變量則放在相鄰的另外一塊內存區中。

2、棧,是由編譯器自動分配和釋放的,主要是函數體的地址,參數和局部變量,靜態變量不包含其中,操作方式類似于數據結構中的棧。

3、堆,是由程序員手動完成申請和釋放的,像malloc和new,程序員沒有手動釋放的話,當程序結束時由系統釋放沒有釋放的空間,其實現方式與數據結構中的堆完全不同,此時的堆的實現方式有些類似于數據結構中的鏈表。

4、程序代碼區,用于存放程序的二進制代碼的空間。

5、文字常量區,像常量字符串等存放在這里,程序結束后由系統釋放。

一個經典的例子,由強大的網友提供:

//main.cppint a = 0; //全局初始化區char *p1; //全局未初始化區main(){int b; //棧char s[] = "abc"; //棧char *p2; //棧char *p3 = "123456"; //123456\0在常量區,p3在棧上。static int c =0; //全局(靜態)初始化區p1 = (char *)malloc(10);p2 = (char *)malloc(20);//分配得來得10和20字節的區域就在堆區。strcpy(p1, "123456"); //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。}

二、內存分配中堆和棧的區別

1.申請釋放方式

?? 在申請內存和釋放內存方式方面,堆和棧有著很大的不同,先來談談棧是如何實現的吧。棧是編譯器自動申請的,例如在主函數里面,要聲明一個int變量a,那么編譯器就自動開辟一塊內存存放變量a。而堆則不相同,是由程序員手動申請的,只要程序員感覺程序此處需要用到多大的內存空間,那么就使用malloc或者new來申請固定大小的內存使用。棧的空間在程序結束的時候由系統或者編譯器自動釋放,而堆則在程序結束前由程序員手動使用delete釋放,或者忘記手動釋放,由系統在程序結束的時候自動回收。

2.申請后系統的相應

棧,只要棧剩余的空間大小比申請的空間小,系統就自動為其分配空間,否則就會報錯說明棧空間溢出。

堆,首先要知道操作系統中有一個存放空閑存儲塊的鏈表,當程序員申請空間的時候,系統就會遍歷整個鏈表,找到第一個比申請空間大的空閑塊節點,系統會將該空閑塊從空閑鏈表中刪除,分配給程序,同時系統會記錄這個空閑塊的首地址和申請的大小,當程序員使用delete釋放該空間的時候能夠找到該存儲區。另外,申請的空間不一定與找到的空閑塊大小相同,多出來剩余的空閑區會被系統重新添加到空閑鏈表中。

3.申請的限制

棧,是一種向低地址擴展的數據結構,并且是連續的存儲空間,所以棧頂和棧的最大容量是固定的,在windows下,棧的最大容量是2m或者是1m,是在編譯的時候就已經確定的,當申請空間大于棧的剩余空間的時候,就會報錯說明overflow,所以棧能夠申請的空間是比較有限的。

堆,是一種向高地址擴展的數據結構,并且是不連續的,因為系統采用的是鏈表的方式存放空閑存儲塊,當然是不連續的,鏈表的遍歷方向是由低向高的,所以堆能夠申請的空間的大小其實等同于整個系統的虛擬內存,只要還有內存空間,那么堆就能夠不受限制的申請空間,這種方式比較靈活,申請空間也較大。

4.申請效率的比較

棧,因為棧空間的申請是由系統自動完成的,所以速度快,但是不受程序員控制。

堆,空間的申請是由malloc或new來完成的,實現起來較慢,能夠產生碎片,但是使用起來方便。

5.存放內容

棧,棧存放的內容,一般來說是函數地址和相關參數。當主函數要調用一個函數的時候,要對當前斷點進行保存,需要使用棧來實現,首先入棧的是主函數下一條語句的地址,然后是調用函數的參數,一般情況下是按照從右向左的順序入棧,之后是調用函數的局部變量,注意靜態變量是存放在全局內存區,是不入棧的;出棧的順序正好相反,最終棧頂指向主函數下一條語句的地址,主程序又從該地址開始執行。

堆,一般情況堆頂使用一個字節的空間來存放堆的大小,而堆中具體存放內容是由程序員來完成的。

參考資料:http://zhidao.baidu.com/question/6117772.html

補充:

全局變量、局部變量、全局靜態變量、局部靜態變量的區別。要從分配內存的位置和作用域入手來解釋。

全局變量,分配的內存在靜態存儲區內存上面,其作用域是全局作用域,也就是整個程序的生命周期內都可以使用,同時,有些程序并不是由一個源文件構成的,可能有許多個源文件構成,全局變量只要在一個文件中定義,就可以在其他所有的文件中使用,當然,必須在其他文件使用extern關鍵字聲明該變量。

局部變量,分配內存是分配在棧存儲區上的,其作用域也只是在局部函數內,在定義該變量的函數內,只要出了該函數,該局部變量就不再起作用,該變量的生命周期也只是和該函數同在。

全局靜態變量,分配的內存與全局變量一樣,也是在靜態存儲內存上,其生命周期也是與整個程序同在的,從程序開始到結束一直起作用,但是與全局變量不同的是,全局靜態變量作用域只在定義它的一個源文件內,其他源文件不能使用它。

局部靜態變量,分配的內存也是在靜態存儲內存上的,其第一次初始化后就一直存在直到程序結束,該變量的特點是其作用域只在定義它的函數內可見,出了該函數就不可見了。

總結

以上是生活随笔為你收集整理的内存分配方式以及堆和栈的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。