C語言學習筆記——堆和棧——未整理,c語言學習筆記
C語言筆記
棧區
棧stack是一種先進後出的內存結構,所有的自動變量,函數的形參都是由編譯器自動放出棧中,當一個自動變量超出其作用域時,自動從棧中彈出。出入棧是由C語言編譯器自動分配釋放。
棧不會很大,一般都是以K為單位。
棧溢出:當棧空間已滿,但還往棧內存壓變量,叫做棧溢出。
速度較快,效率較高
堆區
堆heap和棧一樣,也是一種在程序運行過程中可以隨時修改的內存區域,但是沒有棧那樣先進後出的順序。
堆是一個大容器,它的容量要遠大於棧,在C語言中,對內空間的申請和釋放需要手動通過代碼來完成。堆使用完後必須釋放。速度較慢,效率較低。
堆的分配和釋放——malloc()和free()(在stdlib.h中定義)
靜態區(static)——存儲全局變量和靜態變量。程序結束後由系統自動釋放。
代碼區(code)——存放函數的程序代碼,執行的過程中不能修改。
不能將一個棧變量的地址通過函數的返回值返回。
即:在函數中定義的變量地址不能作為該函數的返回值。
函數可以通過返回值返回一個堆地址,但是在後邊一定要配合free()使用。
//*************************************
int *geta()//錯誤,棧地址不能作為函數返回值
{
int a = 0;
return &a;
}
//*************************************
int *getb() //正確,申請的堆空間可以作為函數返回值,要配合free()函數使用
{
int *p = malloc();
return p;
}
//************************************
int *getc() //正確,static變量在靜態區,程序運行,地址一直有效,不能使用free()釋放
{
static int a = 0;
return &a;
}
//************************************
void getheap(int *p) //p是形參,定義在棧中,函數執行完後,p被釋放,p所指向的堆空間沒有被釋放,導致p指向的具體堆空間的地址丟失。
{
p = malloc();
}
int main()
{
int *p = NULL;
getheap(p);
......
free(p);
return 0;
}
//錯誤
//***********************************
void getheap(int **p) //正確
{
*p = malloc();
}
int main()
{
int *p = NULL;
getheap(p);
......
free(p);
return 0;
}
//***********************************
int *getheap(int *p) //正確
{
p = malloc();
return p;
}
int main()
{
int *p = NULL;
p = getheap(p);
......
free(p);
return 0;
}
//***********************************
2、堆棧和內存映射
每個線程都有自己專屬的棧,先進後出
棧的最大尺寸固定超出則會引起棧溢出
變量離開作用范圍後,棧上的數據會自動釋放
堆上內存必須手工釋放,
int main()
{
int i = 0;
scanf("%d", &i);
int array[i]; //錯誤,定義數組時,數組長度必須是常量,不能是變量
int *array = malloc();
]
明確知道數據占用多少內存,數據量很小——使用棧空間
不確定需要多少內存,大量數據——使用堆空間
堆(heap):由程序員控制,使用malloc/free操作
棧(stack):預先設定大小,自動分配與釋放
堆和棧占用內存數據區空間
內存映射:
棧:
棧頂從高地址向低地址方向增長
存儲非靜態局部變量、函數參數、返回地址
C語言中函數的參數列表是從右往左入棧的
堆的分配和釋放
在Linux下查看C語言程序內存使用情況:
編寫C語言程序,編譯運行,ps -u test——查看進程PID,cd /proc,cd PID,cat maps——顯示內存使用情況,cat smaps——顯示更詳細的內存使用情況。
操作系統在管理內存時,最小單位不是字節,而是內存頁,內存頁大小一般為4K
32位系統最多管理4GB內存
calloc()函數在堆空間中定義一塊內存,並將其初始化為0;
realloc(NULL, 5); 等同於 malloc(5);