一.linux記憶體配置
linux記憶體配置簡單意義來講分為四段
1.代碼區
2.全域變數區
3.棧
4.堆
通過以下程式驗證
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int add(int a,int b){return a+b;}int a1=1;static int a2=2;const int a3=3;int a4;main(){int b1=4;static b2=5;const b3=6;int *p1=malloc(4);printf("a1:%p\n",&a1);printf("a2:%p\n",&a2);printf("a3:%p\n",&a3);printf("a4:%p\n",&a4);printf("b1:%p\n",&b1);printf("b2:%p\n",&b2);printf("b3:%p\n",&b3);printf("p1:%p\n",p1);printf("main:%p\n",main);printf("add:%p\n",add);printf("%d\n",getpid());while(1);}
補充一下:
地址分別是堆>棧>全域區>代碼區
運行效果圖
發現a1是在全域去,a2是在全域區,a3是在代碼區(要注意,const變數是在代碼區)
a4在全域區,b1在棧區,b2在全域區,b3在棧區,p1在堆區,main和add都在代碼區
綜上所述:
1. 普通全域變數在在全域區分配
2. Static不管局部還是全域變數都在全域區
3. 全域const變數分配在代碼區,局部const變數分配在棧區
4. Malloc分配在堆
5. 代碼都是分配在代碼區 二.堆和棧的驗證 上代碼
#include <stdio.h>#include <stdlib.h>#include <unistd.h>main(){int a1=10;int a2=20;int a3=30;int *p1=malloc(4);int *p2=malloc(4);int *p3=malloc(4);printf("%p\n",&a1);printf("%p\n",&a2);printf("%p\n",&a3);printf("%p\n",p1);printf("%p\n",p2);printf("%p\n",p3);printf("%d\n",getpid());while(1);}
運行效果圖如下:
為什麼都是int類型,棧佔用4個位元組,而堆卻佔用16位元組呢(忽略位元組對齊)。
->malloc在低層是通過鏈表形式維護,大概是:malloc memory + 前一個地址指標(4個byte)+ 後一個地址指標(4個byte)+ 本次申請記憶體size(4個byte)
所以init型malloc後是16byte
而棧是壓棧存在,一個接著一個,所以以上棧的間隔是4byte(int型size)
為了驗證以上說法:做一個malloc的驗證
代碼如下:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>main(){int *p1=malloc(4);int *p2=malloc(4);int *p3=malloc(4);*p1=1;*(p1+1)=2;*(p1+2)=3;*(p1+3)=4;*(p1+4)=5;*(p1+5)=6;*(p1+6)=7;*(p1+7)=8;printf("%d\n",*p2);free(p1);}
P2會輸出什麼呢。運行結果會是什麼呢。
P2的輸出結果是5,原因是:從p1 offset 16個byte
*(p1+4)=5;是這個
但是free會造成
*** glibc detected *** ./main: free(): invalid next size(fast): 0x099bc008 ***
Free的時候出錯,因為我們把整個malloc的鏈表結構損壞了,導致free出錯
所以程式中最忌諱有malloc後越界訪問情況