動態記憶體分配初探
記憶體分配有定長記憶體分配也有動長記憶體分配,2者各有優缺點,前者尋址的時間復雜度O(1),后者O(n),對于實時性比較高的場景來說很明顯前者比較適合,且前者不易造成記憶體碎片化,后者則更靈活,想要多少就分多少,比較能節省記憶體,
記憶體碎片化,也就是很難申請到一段連續的堆空間(比如陣列),目前博主知道的解決方法可以通過單鏈表或者雙向鏈表的方式把這些碎片的記憶體連起來,而又是由于鏈表的弊端,造成這部分尋址時間會比較長,所以有些設備如果不重啟的話會越用越卡,這可能是原因之一,
那定長記憶體分配,定多長? 看以下代碼:
int* p1 = (int*)malloc(sizeof(int) * 4);
int* p2 = (int*)malloc(sizeof(int) * 8);
int* p3 = (int*)malloc(sizeof(int) * 12);
int* p4 = (int*)malloc(sizeof(int) * 17);
int* p5 = (int*)malloc(sizeof(int) * 19);
int* p6 = (int*)malloc(sizeof(int) * 1);
int* p7 = (int*)malloc(sizeof(int) * 2);
int* p8 = (int*)malloc(sizeof(int) * 3);
char* p9 = (char*)malloc(sizeof(char) * 1);
char* p10 = (char*)malloc(sizeof(char) * 2);
char* p11 = (char*)malloc(sizeof(char) * 3);
printf("p1 addr is %x\n",p1);
printf("p2 addr is %x\n",p2);
printf("p3 addr is %x\n",p3);
printf("p4 addr is %x\n",p4);
printf("p5 addr is %x\n",p5);
printf("p6 addr is %x\n",p6);
printf("p6 addr is %x\n",p7);
printf("p8 addr is %x\n",p8);
printf("sizeof(int) is %d\n",sizeof(int));
printf("---------------------\n");
printf("p9 addr is %x\n",p9);
printf("p10 addr is %x\n",p10);
printf("p11 addr is %x\n",p11);

p1->p2: 4*16byte = 64byte p1開始申請了16byte的資料
p2->p3: 4*16byte = 64byte p2開始申請了32byte的資料
p3->p4: 6*16byte = 96byte p3開始申請了48byte的資料
p4->p5: 8*16byte = 128byte p4開始申請了68byte的資料
p5->p6: 8*16byte = 128byte p5開始申請了76byte的資料
p6->p7: 4*16byte = 64byte p6開始申請了4byte的資料
p7->p8: 4*16byte = 64byte p7開始申請了8byte的資料
char
p8->p9: 4*16byte = 64byte p8開始申請了12byte的資料
p9->p10: 4*16byte = 64byte p9開始申請了1byte的資料
p10->p11: 4*16byte = 64byte p10開始申請了2byte的資料
由以上分析可見:
定長申請一次申請 64 byte,也就是從一開始的地址處,+63都是有效的,+ 到第64位時應該會報錯,所以下面做一個測驗

果然*(p11+64)后就直接報錯了,去掉*(p11+64)就又好了

正確,從列印的結果及之前的積累又可以得知:除了靜態區的變數被編譯器初始化為0外,其他區域的都是隨機值
所以不管大小都是分配隨機值看起來很浪費,那如何不定長分配呢?
請看下回分解
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287225.html
標籤:其他
