目錄
代碼區
數據區
堆區?
?棧區
?常量區
重點比較一下堆區與?棧區?
總結:
?
前言:
C語言程序的內存分配區域是理解其運行機制的重要部分。根據提供的多條證據,我們可以總結出C語言程序在運行時主要涉及以下五個關鍵內存區域:?代碼區、?數據區?、?堆區?、?棧區??和?常量區。這些區域各自承擔不同的功能,。
那么本章節為大家講解定義,作用和特點。
堆區,棧區在動態內存的習題章節出現過,不知道大家是否還記得。
這個問題留的在最后,看完本章節,就兩字? 通透。
代碼區
- 定義:代碼區存儲程序的機器代碼,即編譯后的二進制指令。這部分內存通常是只讀的,以防止程序意外修改自身的指令。
- 作用:CPU在執行程序時,會從代碼區加載指令并依次運行。代碼區的內容在程序運行期間不會改變。
查看
- 特點:代碼區通常位于內存的低地址部分,操作系統負責加載和保護該區域
數據區
- 定義:數據區分為已初始化數據區和未初始化數據區。已初始化數據區存儲全局變量和靜態變量,而未初始化數據區存儲全局未初始化變量。
- 作用:存儲程序運行時需要保留的數據,包括全局變量和靜態變量。這些變量在整個程序運行期間都存在,并在程序結束時被釋放。
- 特點:數據區是只讀或可讀寫的區域,具體取決于變量是否被初始化。
堆區?
- 定義:堆區用于動態內存分配,程序員通過函數如
malloc
、calloc
、realloc
等分配內存空間,用于存儲運行時需要額外分配的變量。 - 作用:動態分配的內存可以在程序運行過程中隨時調整大小或釋放。堆區的管理較為靈活,但如果不及時釋放可能導致內存泄漏。
查看
- 特點:堆區的內存分配方式類似于鏈表,分配和釋放較為復雜,且容易產生碎片
?棧區
- 定義:棧區用于存儲函數調用時的局部變量、函數參數以及返回地址等信息。棧區由編譯器自動分配和釋放,通常在函數調用結束后立即釋放。
- 作用:棧區主要用于存放生命周期較短的變量,如局部變量和形參。它支持快速分配和釋放,因此非常適合處理短期數據。
- 特點:棧區的內存分配方式類似于數據結構中的棧,遵循“先進后出”的原則。棧區的大小通常較小且連續,但其容量有限,如果過度使用可能導致棧溢出。
?常量區
- 定義:常量區存儲程序中定義的字符串常量和其他只讀數據。
- 作用:常量區中的數據通常是只讀的,例如字符串字面量或符號常量。這些數據在程序運行期間不會被修改。
- 特點:常量區的數據通常位于內存的高地址部分,且在程序結束時不會被釋放。
重點比較一下堆區與?棧區?
存儲內容不同
棧:在函數調用時,棧中存放的是函數中各個參數(局部變量)。棧底下是函數調用后的下一條指令。
堆:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。
管理方式上不同
棧:由系統自動分配空間,同時系統自動釋放空間。例如,聲明在函數中一個局部變量“int b“。系統自動在棧中為b開辟空間,當對應的生存周期結束后棧空間自動釋放。
堆:需要程序員手動申請并且手動釋放,并指明大小。在C語言中malloc函數申請,釋放free函數,在C++中new和delete實現。
空間大小不同
棧:獲取空間較小。在Windows下,一般大小是1M或2M,當剩余棧空間不足時,分配失敗overflow。
堆:獲得空間根據系統的有效虛擬內存有關,比較靈活,比較大。
能否產生碎片不同
棧:不會產生碎片,空間連續。
堆:采用的是鏈表的存儲方式,會產生碎片。
生長方向不同
棧:向低地址擴展的數據結構,是一塊連續的內存的區域。
堆:向高地址擴展的數據結構,是不連續的內存區域。這是由于系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。
分配方式不同
棧:有2種分配方式——靜態分配和動態分配。靜態由編譯器完成,例如局部變量;動態由alloca函數實現,并且編譯器會進行釋放。
堆:都是動態分配的,沒有靜態分配的堆。
分配效率不同
棧:由系統自動分配,速度較快。但程序員是無法控制的。
堆:由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來方便。
總結:
1.棧:用來存放函數的形參和函數內的局部變量。由編譯器分配空間,在函數執行完后由編譯器自動釋放。
2.堆:用來存放由動態分配函數(如malloc)分配的空間。是由程序員自己手動分配的,并且必須由程序員使用free釋放。如果忘記用free釋放,會導致所分配的空間一直占著不放,導致內存泄露。
3.全局區/靜態區:用來存放全局變量和靜態變量。程序結束時由系統釋放,分為全局初始化區和全局未初始化區;存在于程序的整個運行期間,是由編譯器分配和釋放的。
4.常量區:常量字符串放于此,程序結束時由系統釋放。例如char *str=”hello_world”;則”hello_world”為文字常量,存放于文字常量區。也由編譯器控制分配和釋放。
5.代碼區:用來存放程序的二進制代碼。
提供一個代碼,供大家理解?
#include <stdlib.h>
#include <string.h>int a = 0; char *p1;
int main()
{int b; //棧char arr[] = "abc"; char *p2; //棧char *p3 = "123456"; static int c =0; p1 = (char *)malloc(10); p2 = (char *)malloc(20); strcpy(p1, "123456"); return 0;
}
?答案如下:
#include <stdlib.h>
#include <string.h>int a = 0; //全局初始化區char *p1; //全局未初始化區int main()
{int b; //棧char arr[] = "abc"; // arr在棧,"abc\0"在常量區char *p2; //棧char *p3 = "123456"; // "123456\0"在常量區,p3在棧上static int c =0; //全局區p1 = (char *)malloc(10); //p1在棧,分配的10字節在堆p2 = (char *)malloc(20); //p2在棧,分配的20字節在堆strcpy(p1, "123456"); //"123456"放在常量區,編譯器可能會優化為和p3的指向同一塊區域return 0;
}