###C語音裡面的記憶體劃分
- 棧區(棧記憶體,存放區域性變數,自動分配和釋放,裡面函式的引數,方法裡面的臨時變數)
- 堆區(動態記憶體分配,C語音裡面由程式設計師手動分配),最大值為作業系統的80%
- 全域性區(靜態區)
- 常量區(字串)
- 程式程式碼區
###靜態與動態記憶體分配
- 在程式執行過程中,動態指定需要使用的記憶體大小,手動釋放,釋放之後這些記憶體還可以被重新使用。
- 靜態記憶體分配,分配記憶體大小的是固定,問題:1.很容易超出棧記憶體的最大值 2.為了防止記憶體不夠用會開闢更多的記憶體,容易浪費記憶體。
###棧溢位
void main(){
//下面的程式碼會導致棧溢位
//屬於靜態記憶體分配,分配到棧裡面,Window裡面每一個應用棧大概是2M,大小確定。與作業系統有關。
int a [1024 * 1024 * 10 * 4];
}
複製程式碼
###動態記憶體分配與釋放
//堆存分配,40M
//引數:位元組 KB M 10M 40M
//開闢
int* p1 = (int*)malloc(1024*1024*10*sizeof(int));
//釋放
free(p1);
複製程式碼
###通過動態記憶體分配來動態指定陣列的大小
int len;
len = scanf("%d" , &len);
int* arr = (int*)malloc(len * sizeof(int));
//另外一種方法
//(int*)calloc(len , sizeof(int));
//p是陣列的首地址,p就是陣列的名稱
//給陣列元素賦值(使用這一塊剛剛開闢出來的記憶體區域)
int i = 0;
for (; i < len - 1; i++){
arr[i] = rand() % 100;
printf("%d,%#x\n", arr[i], &arr[i]);
}
free(arr);
複製程式碼
###重新分配realloc
//重新分配記憶體的兩種情況:
//縮小,縮小的那一部分資料會丟失
//擴大,(連續的)
//1.如果當前記憶體段後面有需要的記憶體空間,直接擴充套件這段記憶體空間,realloc返回原指標
//2.如果當前記憶體段後面的空閒位元組不夠,那麼就使用堆中的第一個能夠滿足這一要求的記憶體塊,將目前的資料複製到新的位置,並將原來的資料庫釋放掉,返回新的記憶體地址
//3.如果申請失敗,返回NULL,原來的指標仍然有效
int addLen =10;
//用realloc來擴大記憶體
//1.原來記憶體的指標 2.記憶體擴大之後的總大小
int* p2 = (int*)realloc(arr,(len +addLen) * sizeof(int) );
//重新給新的陣列賦值
i = 0;
for (; i < len + addLen; i++){
p2[i] = rand() % 200;
printf("%d,%#x\n", p2[i], &p2[i]);
}
複製程式碼
###釋放記憶體的細節問題
- 不能多次釋放(否則會產生中斷)
- 釋放完之後(指標仍然有值),給指標置NULL,標誌釋放完成
- 記憶體洩露(p重新賦值之後,再free,並沒有真正釋放記憶體(之前的記憶體))
####安全釋放的例子 if (p2 != NULL) { free(p2); p2 = NULL; }
####記憶體洩漏的例子
void main(){
//分配40M
int* p = (int*)malloc(1024*1024*40);
//下一次分配之前,如果不釋放,會造成40M的記憶體洩漏
free(p);
p = NULL;
//分配80M
p = (int*)malloc(1024*1024*80);
free(p);
system("pause");
}
複製程式碼
如果覺得我的文字對你有所幫助的話,歡迎關注我的公眾號:
我的群歡迎大家進來探討各種技術與非技術的話題,有興趣的朋友們加我私人微信huannan88,我拉你進群交(♂)流(♀)。