1.代碼區:
代碼區Code,程序被操作系統加載到內存的時候,所有的可執行代碼都加載到代碼區,也叫代碼段,這塊內存是不可以在運行期間修改的。
2.?靜態區
所有的全局變量以及程序中的靜態變量都存儲在靜態區。
#include<stdio> int c = 0;//靜態區 void test(int a,int b) {printf(“%d %d\n”,&a,&b); //在棧區 } int main() {static int d = 0;int a = 0; //棧區int b = 0;printf(“%d %d %d %d %d\n”,&a,&b,&c,main,d);return 0; }
3.堆區
對于一個32位操作系統,最大管理4G內存,其中1G是給操作系統自己用的,剩下的3G都是給用戶程序,一個用戶程序理論上可以使用3G空間
int *p = (int*)malloc(sizeof(int) * 10); //在堆中申請內存,在堆中申請了一個10個int型大小內存。 char *p1 = malloc(sizeof(char) * 10); //在隊中申請10個char這么大的空間free(p);//釋放通過malloc分配的堆內存 free(p1); //釋放通過maclloc分配的對內存
4.棧區
棧stack是一種先進后出的內存結構,所有的自動變量,函數的形參都是由編譯器自動放出棧中,當一個自動變量超出其作用域時,自動從棧中彈出。
對于自動變量,什么時候入棧,什么時候出棧,是不需要程序控制的,由C語言編譯器實現的。
#include<stdio.h> int *geta() //函數的返回值是個指針 {auto int a = 100;return &a; }//int a的作用域就是{} int main() {int *p = geta();//這里得到的是一個臨時變量的地址,這個地址在函數geta調用結束以后已經無效了*p = 100;printf(“%d\n”,*p);return 0; }
?????? 棧不會很大,一般都是K為單位
?????? 棧溢出:當棧空間已滿,但還往棧內存壓變量,這個就叫棧溢出。
int *geta() //錯誤,不能將一個棧變量的地址通過函數的返回值返回 {int a = 0;return &a; }int *geta1() //通過函數的返回值可以返回一個對地址,但記得一定要free {int *p = malloc(sizeof(int));return p; } int main() {int *getp = geta1();*getp = 100;free(getp); }
int *geta2() //合法 {static int a = 100;return &a; } int main() {int *getp = geta2();*getp = 100;//free(getp); }
?
int main() //結果正常。 {int *p = NULL;p = malloc(sizeof(int) * 10);p[0] = 1;p[1] = 2;printf(“p[0] = %d, p[1] = %d\n”,p[0],p[1]); // free(p); }
?
//結果崩潰 void getheap(int *p) {p = malloc(sizeof(int) * 10); } int main() {int *p = NULL;getheap(p);p[0] = 1;p[1] = 2;printf(“p[0] = %d, p[1] = %d\n”,p[0],p[1]); // free(p); }
分析:主函數的p的值NULL ,傳遞給函數getheap中的*p,在函數中malloc分配的內存分配給了函數中的*p,分配的malloc是堆中的,mian中的內存都在棧中的,意味這main函數中的p沒有得到內存地址。
?
修正:
void getheap(int **p) {*p = (int*)malloc(sizeof(int) * 10); } int main() {int *p = NULL;getheap(&p);p[0] = 1;p[1] = 2;printf(“p[0] = %d, p[1] = %d\n”,p[0],p[1]); // free(p); }
這樣就可以給指針p分配內存了。
?