自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C語言動態(tài)內(nèi)存分配

開發(fā) 后端
動態(tài)內(nèi)存分配的好處在于需要內(nèi)存的時候可以按需分配,當(dāng)不需要內(nèi)存的時候可以將其釋放掉,這樣可以高效的利用內(nèi)存。下面本文從零開始實現(xiàn)一個完整的動態(tài)內(nèi)存分配。

 前言

首先要明白為何需要動態(tài)內(nèi)存分配,熟悉C語言的讀者應(yīng)該對這個比較熟悉,需要一段內(nèi)存時會使用malloc函數(shù)來申請所需要大小的內(nèi)存,函數(shù)返回一段內(nèi)存的首地址。簡單來說,動態(tài)內(nèi)存分配的好處在于需要內(nèi)存的時候可以按需分配,當(dāng)不需要內(nèi)存的時候可以將其釋放掉,這樣可以高效的利用內(nèi)存。下面本文從零開始實現(xiàn)一個完整的動態(tài)內(nèi)存分配。

簡單動態(tài)內(nèi)存分配實現(xiàn)

內(nèi)存分配是將沒有使用的內(nèi)存塊給需要的變量(普通變量、指針變量、結(jié)構(gòu)體變量等等)使用,由于其使用后需要進(jìn)行釋放,這就會導(dǎo)致空閑的內(nèi)存是分散在內(nèi)存池中的。因此,必須要對內(nèi)存進(jìn)行管理,也就是對內(nèi)存的使用情況做標(biāo)記。

上圖是一個內(nèi)存池使用后的某一時刻,可以看到,使用的塊和沒有使用的塊并不是連續(xù)的,這樣就需要用一個表對其進(jìn)行標(biāo)記,這個表稱為BitMap。假設(shè)現(xiàn)在將內(nèi)存按照每個Byte進(jìn)行劃分,然后用一個bit對塊進(jìn)行標(biāo)記,1表示已使用,0表示沒有使用,這樣一個塊需要一個bit。

下面來用C語言來實現(xiàn)這個簡單的動態(tài)內(nèi)存分配。 

  1. #include <stdio.h>  
  2. #define MEM_POOL_SIZE  64  
  3. unsigned char MemPool[MEM_POOL_SIZE];  
  4. unsigned char BitMap[MEM_POOL_SIZE/8]={0};  
  5. //BitMap[0] MSB->LSB  MemPool[0 ~ 8]  
  6. //BitMap[1] MSB->LSB  MemPool[9 ~15]  
  7. //BitMap[2] MSB->LSB  MemPool[16~23]  
  8. // ...  
  9. void InitMemAlloc(void)  
  10.  
  11.     int i=MEM_POOL_SIZE 
  12.     while(i--)  
  13.     {  
  14.         MemPool[i]=0;  
  15.     }  
  16.     i=MEM_POOL_SIZE/8;  
  17.     while(i--)  
  18.     {  
  19.         BitMap[i]=0;  
  20.     }  
  21.  
  22. void *MemAlloc(unsigned int m_size)  
  23.  
  24.     unsigned int i=0,j=0,k=0,index=0,count=0,mapv=0,cache;  
  25.     if(m_size>MEM_POOL_SIZE)  
  26.     {  
  27.         return NULL;  
  28.     }  
  29.     else  
  30.     {  
  31.         for(;i<MEM_POOL_SIZE/8;i++)  
  32.         {  
  33.             mapv=BitMap[i];   //取出高位  
  34.             for(j=0;j<8;j++)  
  35.             {  
  36.                 cache=(mapv&0x80);  
  37.                 if(cache==0)  
  38.                 {  
  39.                     count++;  
  40.                     if(count==m_size) 
  41.                     {  
  42.                         for(;k<m_size;k++)  
  43.                         {  
  44.                             BitMap[(index+k)/8]|=(1<<(7-((index+k)%8)));  
  45.                         }  
  46.                         return &MemPool[index];  
  47.                     }  
  48.                 }  
  49.                 else  
  50.                 {  
  51.                     count=0 
  52.                     iindex=i*8+j+1;  
  53.                 }  
  54.                 mapv<<=1;  
  55.             }  
  56.         }  
  57.         return NULL;  
  58.     }  
  59. }   
  60. void MemFree(void *p,unsigned int m_size)  
  61.  
  62.     unsigned int k=0,index=(((unsigned int)p)-(unsigned int)MemPool);  
  63.     for(;k<m_size;k++)  
  64.     {  
  65.         BitMap[(index+k)/8]&=~(1<<(7-((index+k)%8)));  
  66.     }  
  67.  
  68. void MemPrintBitMap(void)  
  69.  
  70.     unsigned int i,j,value;   
  71.      for(i=0;i<MEM_POOL_SIZE/8;i++)  
  72.     {  
  73.         value=BitMap[i];  
  74.         for(j=0;j<8;j++)  
  75.         {  
  76.             if(value&0x80)  
  77.                 printf("1 ");  
  78.             else  
  79.                 printf("0 ");  
  80.             value<<=1;  
  81.         }  
  82.         printf("\n");  
  83.     }  
  84.  
  85. double MemGetUsedPercent(void)  
  86.  
  87.     unsigned int i,j,value;  
  88.     double ret=0.0;  
  89.     for(i=0;i<MEM_POOL_SIZE/8;i++)  
  90.     {  
  91.         value=BitMap[i];  
  92.         for(j=0;j<8;j++)  
  93.         {  
  94.             if(value&0x80)  
  95.                 ret++;  
  96.             value<<=1;  
  97.         }  
  98.     }  
  99.     return (ret*100)/MEM_POOL_SIZE; 
  100.  
  101. int main(int argc, char **argv)  
  102.  
  103.     int *p=MemAlloc(10);  
  104.     printf("The pool is used=%f\n",MemGetUsedPercent());  
  105.     MemPrintBitMap();  
  106.     int *q=MemAlloc(5);  
  107.     printf("The pool is used=%f\n",MemGetUsedPercent());  
  108.     MemPrintBitMap(); 
  109.     MemFree(p,5);  
  110.     printf("The pool is used=%f\n",MemGetUsedPercent());  
  111.     MemPrintBitMap();  
  112.     return 0;  

最終終端輸出結(jié)果如下:

上面已經(jīng)實現(xiàn)了一個簡單的動態(tài)內(nèi)存分配,可以完成內(nèi)存的分配和釋放以及輸出使用率和查看位圖。這種方式實現(xiàn)的動態(tài)內(nèi)存分配不會產(chǎn)生內(nèi)部碎片,這也是其優(yōu)勢所在,但其缺點很明顯就是利用率太低。

實用的動態(tài)內(nèi)存分配

細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn)上面的簡單動態(tài)內(nèi)存分配有一個缺點,就是一個bit只能表示一個字節(jié),也就是說表示8個字節(jié)就需要一個字節(jié)的位圖,這種映射導(dǎo)致其內(nèi)存的

這對于很多情況是比較浪費的。為了提高利用率,就必須將映射塊的粒度增大,也就是一個Bit的映射范圍對應(yīng)多個字節(jié)。

上圖給出了一個bit映射到64Byte,這樣:

雖然利用率變高了,但是其會產(chǎn)生內(nèi)部碎片,所謂內(nèi)部碎片就是在最小粒度內(nèi)無法使用的內(nèi)存空間,為何這個空間無法使用了,原因在于當(dāng)在申請內(nèi)存塊的時候,其內(nèi)存只能以64B對齊的,即使小于64B,也得按64B來看作,因為這個粒度已經(jīng)被bitmap標(biāo)記使用了,當(dāng)下次使用時,其無法被分配。因此,可以看到,粒度越大,其可能產(chǎn)生的內(nèi)部內(nèi)存碎片越大,內(nèi)存利用率和碎片是需要權(quán)衡了,好的算法只能解決外部碎片問題,無法解決內(nèi)部碎片問題,因此在實現(xiàn)動態(tài)內(nèi)存分配時必須權(quán)衡考慮,以達(dá)到最優(yōu)結(jié)果。 

 

責(zé)任編輯:龐桂玉 來源: C語言與C++編程
相關(guān)推薦

2022-01-07 15:10:53

C++動態(tài)內(nèi)存

2022-03-18 22:39:57

動態(tài)內(nèi)存malloc

2011-07-20 13:47:14

CC++

2021-12-16 06:52:33

C語言內(nèi)存分配

2010-08-18 10:05:28

Hyper-V動態(tài)內(nèi)存

2010-12-09 10:03:17

Hyper-V R2

2010-03-02 08:53:59

Windows 8動態(tài)內(nèi)存

2010-03-01 09:09:21

Windows 8動態(tài)內(nèi)存

2024-01-26 16:28:28

C++動態(tài)內(nèi)存開發(fā)

2022-04-26 06:21:59

編程動態(tài)內(nèi)存

2012-04-01 14:38:06

Windows Ser虛擬化

2025-03-26 00:00:05

2021-12-22 06:56:07

STM32C語言內(nèi)存

2018-06-06 08:28:37

Spark內(nèi)存管理

2010-02-04 14:58:06

C++內(nèi)存分配

2011-07-28 10:03:53

Hyper-V動態(tài)內(nèi)存

2010-01-25 14:56:08

C++程序

2022-01-07 13:50:55

語言內(nèi)存代碼

2011-07-15 01:10:13

C++內(nèi)存分配

2015-11-26 11:02:37

微軟LinuxHyper-V
點贊
收藏

51CTO技術(shù)棧公眾號