在學內存分配的問題的時候,malloc和calloc都要指定需要分配內存的大小,但是free的就不需要,我就納悶free是咋知道從指針地址開始的多少長度是被分配了的?
當時就想,在malloc或者calloc的時候,編譯器應該把大小的數值放到哪個地方了,當free的時候就去找那個數值,釋放掉數值大小的堆空間。
但是到底放哪呢?
前幾天在網上一陣亂逛,說是現代編譯器就是把大小的數值放在分配地址開始的之前位置,但是具體在之前多少位置呢?今天在vs的內存監視器裡面看到了。
測試代碼如下:
[cpp]
#include "stdlib.h"
#include "stdio.h"
#define Num 100
int main(void)
{
int i;
int *p=(int *)malloc(Num);
for (i=0;i<Num;i++)
{
*(p+i)=1; //賦值為1只是為了看起來方便
}
free(p);
return 0;
}
其中p的地址為0x00393220
接著打開vs2008的內存監視器窗口看:
有一個地址為0x00393210的很可疑,因為0x64=100
那麼改一下看看:
[cpp]
#define Num 50
再看內存監視器:
看到*(0x00393210)=0x32;即0x32=50
那應該就是把大小放這裡了,就是說距離分配地址0x10之前的位置。
從中可以看出為什麼分配堆更號內存大小(當然它的主要方面還是“碎片”的產生)的一個小方面~~~
那麼calloc又是如何呢?答案就是和malloc一樣,把原來的size換成num*size;
[cpp]
#include "stdlib.h"
#include "stdio.h"
#define Num 50
int main(void)
{
int i;
int *p=(int *)calloc(Num,Num);
for (i=0;i<Num;i++)
{
*(p+i)=1;
}
free(p);
return 0;
}
這裡的p地址是0x00395008。
0x9c4=2500(這裡有大小端的知識,呵呵,可以看出來x86是小端:MSB存高地址)
這對於存放內存空間大小的數值是足夠的,因為calloc和malloc的函數原型:
[cpp]
void *malloc(size_t size);
void *calloc(size_t num,size_t size);
ps:size_t在內部被宏定義為unsigned int。
這樣豈不是說calloc可以把整個內存都分配了,那當然不行,如何你申請的堆內存空間過大,則會發生以下錯誤(vs2008):
中間那句話很簡潔明了吧,至於我輸了多大的值,大家可以試試,其實話說在ARM和DSP(針對MCU),堆和棧的大小和起始地址都是可以手動分配的,你當然不能超過了~~~
但是還有問題:是不是存大小的位置和編譯器有關呢?和CPU有關否?
To Be Continued~~~
ps:手中剛好有一塊Cortex-M3的板子,可以用MDK來編譯Debug下就明了了~~~