C語言記憶體分配:
靜態記憶體:也就是棧空間記憶體,不用程式設計師自己分配。
1、棧區(stack):編譯器在需要的時候分配,在不需要的時候自動清除的變數的儲存區。棧裡面的變數通常是區域性變數、函式引數等。windows下,棧記憶體分配2M(確定的常數),超出了限制,提示stack overflow錯誤。自動分配,釋放。
動態記憶體分配:由 malloc 等分配的記憶體塊,和堆是十分相似的,不過它是用 free 來結束自己的生命的。
2、堆區(heap):由 new 分配的記憶體塊,他們的釋放編譯器不去管,由我們的應用程式去控制,一般一個 new 就要對應一個 delete。如果程式設計師沒有釋放掉,那麼在程式結束後,作業系統會自動回收。堆可以動態地擴充套件和收縮。 程式設計師手動分配釋放,作業系統80%記憶體。
3、全域性區或靜態區。
4、字元常量區。
5、程式程式碼區。
void main(){
//靜態記憶體分配,在棧記憶體中
int a[100*1024*1024];
getchar();
}
複製程式碼
會出現stack overflow錯誤,也就是棧溢位。
void main(){
//動態記憶體分配
int* p = malloc(1024*1024*sizeof(int));
//printf("%#x\n",p);
//釋放
free(p);
getchar();
}
複製程式碼
上面就是使用malloc動態分配sizeof(int)M記憶體,然後使用free釋放分配的記憶體。
靜態記憶體分配:分配固定大小的記憶體空間。 存在問題:1、容易超出棧記憶體最大值,也就是造成棧溢位。 2、為了防止記憶體不夠用會開闢更多的空間,容易浪費記憶體。
動態記憶體分配:在程式執行過程中,動態指定需要使用的記憶體大小,手動釋放,釋放之後這些記憶體還可以被重新使用。
建立一個陣列,動態指定陣列的大小
void main(){
int size;
scanf("%d",&size);
//開闢記憶體,大小size*sizeof(int)位元組
int* p = malloc(size*sizeof(int));
//p是陣列的首地址,p就是陣列的名稱
//給陣列元素賦值(使用這一塊剛剛開闢出來的記憶體區域)
int i = 0;
for (; i < size; i++){
p[i] = rand() % 300;
printf("%d %#x\n", p[i], &p[i]);
}
//釋放p
free(p);
getchar();
}
複製程式碼
realloc :重新分配記憶體
void main(){
int size;
scanf("%d",&size);
//開闢記憶體,大小size*sizeof(int)位元組
int* p = malloc(size*sizeof(int));
//p是陣列的首地址,p就是陣列的名稱
//給陣列元素賦值(使用這一塊剛剛開闢出來的記憶體區域)
int i = 0;
for (; i < size; i++){
p[i] = rand() % 300;
printf("%d %#x\n", p[i], &p[i]);
}
int addSize;
printf("輸入陣列增加的長度:");
scanf("%d", &addSize);
//記憶體不夠用,擴大剛剛分配的記憶體空間
int* p2 = realloc(p, (addSize + size)*sizeof(int));
if (p2 == NULL){
printf("重新分配失敗");
}
//重新賦值
int j = 0;
printf("\n\n");
for (; j < (size + addSize); j++){
p2[j] = rand() % 100;
printf("%d %#x\n", p2[j], &p2[j]);
}
//手動釋放記憶體
if (p != NULL){
free(p);
p = NULL;
}
if (p2 != NULL){
free(p2);
p2 = NULL;
}
getchar();
}
複製程式碼
重新分配記憶體的兩種情況: 1、縮小,縮小的那一部分資料會丟失 2、擴大,(連續的) (1)如果當前記憶體段後面有需要的記憶體空間,直接擴充套件這段記憶體空間,realloc返回原指標; (2)如果當前記憶體段後面的空閒位元組不夠,那麼就使用堆中的第一個能夠滿足這一要求的記憶體塊,將目前的資料複製到新的位置,並將原來的資料庫釋放掉,返回新的記憶體地址; (3)如果申請失敗,返回NULL,原來的指標仍然有效。
記憶體分配的幾個注意細節: 1.不能多次釋放 2.釋放完之後(指標仍然有值),給指標置NULL,標誌釋放完成 3.記憶體洩露(p重新賦值之後,再free,並沒有真正釋放記憶體)