【C语言天天练(二四)】内存分配
引言:
? ? ??
? ? ? ? 對于C語言程序,了解它執行時在內存中是怎樣分配的對于我們理解它的執行機制是很實用的。以下就總結一下C語言程序的一些內存分配知識。
一
? ? ? ? 一段C程序。編譯連接后形成的可運行文件一般有代碼段、數據段、堆和棧等幾部分組成。當中數據段又包含僅僅讀數據段、已初始化的讀寫數據段和未初始化的BSS段。例如以下圖所看到的:
文本段:存放程序運行的代碼。
數據段:
1>僅僅讀數據段:
僅僅讀數據段是程序使用的一些不會被更改的數據,使用這些數據的方式類似查表式的操作,因為這些變量不須要更改,因此僅僅須要放置在僅僅讀存儲器中就可以。
通常是const修飾的變量以及程序中使用的文字常量通常會存放在僅僅讀數據段中。
2>已初始化的讀寫數據段:
已初始化數據是在程序中聲明,而且具有初值的變量。這些變量須要占用存儲器的空間,在程序執行時它們須要位于可讀寫的內存區域內。而且有初值,以供程序執行時讀寫。在程序中一般為已經初始化的全局變量,已經初始化的靜態局部變量(static修飾的已經初始化的變量)
3>未初始化段(BSS):
未初始化數據是在程序中聲明,可是沒有初始化的變量,這些變量在程序執行之前不須要占用存儲器的空間。
與讀寫數據段類似,它也屬于靜態數據區。
可是該段中數據沒有經過初始化。
未初始化數據段僅僅有在執行的初始化階段才會產生,因此它的大小不會影響目標文件的大小。在程序中通常是沒有初始化的全局變量和沒有初始化的靜態局部變量。
棧:由系統自己主動分配。比如,聲明在函數中一個局部變量int b;系統自己主動在棧中為b開辟空間。
二
依據上面的理論知識,分析演示樣例片段的內存分配:
三
棧與堆的差別:
1.申請方式
(1)棧(satck):由系統自己主動分配。比如,聲明在函數中一個局部變量int b;系統自己主動在棧中為b開辟空間。
(2)堆(heap):需程序猿自己申請(調用malloc,realloc,calloc),并指明大小,并由程序猿進行釋放。
easy產生memory leak.
eg:char? p;
????? p = (char *)malloc(sizeof(char));
可是,p本身是在棧中。
2.申請大小的限制
(1)棧:棧是向底地址擴展的數據結構,是一塊連續的內存區域(它的生長方向與內存的生長方向相反)。棧的大小是固定的。假設申請的空間超過棧的剩余空間時,將提示overflow。
(2)堆:堆是高地址擴展的數據結構(它的生長方向與內存的生長方向同樣)。是不連續的內存區域。這是因為系統使用鏈表來存儲空暇內存地址的。自然是不連續的,而鏈表的遍歷方向是由底地址向高地址。
堆的大小受限于計算機系統中有效的虛擬內存。
3.系統響應:
(1)棧:僅僅要棧的空間大于所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。
(2)堆:首先應該知道操作系統有一個記錄空暇內存地址的鏈表,但系統收到程序的申請時,會遍歷該鏈表。尋找第一個空間大于所申請空間的堆結點。然后將該結點從空暇鏈表中刪除。并將該結點的空間分配給程序,另外,對于大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小。這樣。代碼中的free語句才干正確的釋放本內存空間。另外。找到的堆結點的大小不一定正好等于申請的大小,系統會自己主動的將多余的那部分又一次放入空暇鏈表中。
說明:對于堆來講,頻繁的malloc/free勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率減少。對于棧來講。則不會存在這個問題,
4.申請效率
(1)棧由系統自己主動分配,速度快。但程序猿是無法控制的
(2)堆是由malloc分配的內存,一般速度比較慢,并且easy產生碎片。只是用起來最方便。
5.堆和棧中的存儲內容
(1)棧:在函數調用時,第一個進棧的主函數中后的下一條語句的地址。然后是函數的各個參數,參數是從右往左入棧的,然后是函數中的局部變量。注:靜態變量是不入棧的。
當本次函數調用結束后。局部變量先出棧。然后是參數,最后棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
(2)堆:通常是在堆的頭部用一個字節存放堆的大小。
6.存取效率
(1)堆:char *s1=”hellow?tigerjibo”;是在編譯是就確定的
(2)棧:char s1[]=”hellow?tigerjibo”;是在執行時賦值的;用數組比用指針速度更快一些,指針在底層匯編中須要用edx寄存器中轉一下,而數組在棧上讀取。
補充:
棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令運行。這就決定了棧的效率比較高。
堆則是C/C++函數庫提供的,它的機制是非常復雜的,比如為了分配一塊內存。庫函數會依照一定的算法(詳細的算法能夠參考數據結構/操作系統)在堆內存中搜索可用的足夠大小的空間,假設沒有足夠大小的空間(可能是因為內存碎片太多)。就有可能調用系統功能去添加程序數據段的內存空間。這樣就有機會分到足夠大小的內存,然后進行返回。顯然。堆的效率比棧要低得多。
7.分配方式:
(1)堆都是動態分配的,沒有靜態分配的堆。
(2)棧有兩種分配方式:靜態分配和動態分配。靜態分配是編譯器完畢的。比方局部變量的分配。
動態分配由alloca函數進行分配,可是棧的動態分配和堆是不同的。
它的動態分配是由編譯器進行釋放,無需手工實現。
四
參考1:http://blog.csdn.net/tigerjibo/article/details/7423728
參考2:http://blog.csdn.net/to_be_it_1/article/details/31420549
參考3:http://blog.csdn.net/lovecodeless/article/details/24384093
參考4:http://blog.csdn.net/lovecodeless/article/details/21084513
轉載于:https://www.cnblogs.com/yxwkf/p/5115601.html
總結
以上是生活随笔為你收集整理的【C语言天天练(二四)】内存分配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第 五 课 golang语言变量
- 下一篇: springboot和quartz整合实