2016-04-14 36 views
0

C'ye basit bir bellek havuzu oluşturdum ve ayrıca bu havuzda bellek bloklarını uygulama becerisini de uyguladım.C Bellek Havuzunda Bellek Bloklarını Birleştirin

Bellek bloklarının kendileri oldukça basittir, yalnızca ücretsiz bir bayrak ve boyut özelliği olan bağlantılı bir liste.

Şu an yapmaya çalıştığım şey, bellek havuzuma bir işaretçi alan ve içindeki bellek bloklarını birleştiren bir işlev oluşturmaktır, böylece ayrılmış (boşta == 0) bloklar havuzun başlangıcına ve ayrılan bloklara doğrudur. havuzun sonuna doğru. Örneğin

, benim Birleştirmek işlevi aramadan önce hafıza blokları bu gibi yapılandırılmış olsaydı:

Block Size: 25 (41 w/ header), Free: 1 
Block Size: 100 (116 w/ header), Free: 0 
Block Size: 25 (41 w/ header), Free: 1 
Block Size: 100 (116 w/ header), Free: 0 
Block Size: 100 (116 w/ header), Free: 0 
Block Size: 54 (70 w/ header), Free: 1 

Sonra işlevini çağırarak sonra bloklar şöyle düzenlenebilir olacaktır:

Block Size: 100 (116 w/ header), Free: 0 
Block Size: 100 (116 w/ header), Free: 0 
Block Size: 100 (116 w/ header), Free: 0 
Block Size: 25 (41 w/ header), Free: 1 
Block Size: 25 (41 w/ header), Free: 1 
Block Size: 54 (70 w/ header), Free: 1 

Fonksiyonu oluşturmayı denedim ancak fonksiyondan sonra çıkışım olduğu gibi, etraftaki doğru blokları hareket ettirmek gibi bir problemle karşılaştım:

Block Size: 100 (116 w/ header), Free: 0 
Block Size: 25 (41 w/ header), Free: 1 
Block Size: 100 (116 w/ header), Free: 0 
Block Size: 1744830464 (1744830480 w/ header), Free: 21 

Fonksiyonun yanlış işlemleri gerçekleştirdiği yerde hiç emin değilim, bu yüzden birilerinin benim için biraz ışık tutacağını umuyorum.

Benim Birleştirmek fonksiyonu:

void defragment(Pool* pool) 
{ 
    if(pool && pool->root) 
    { 
     Block* current = pool->root; 

     while(current) 
     { 
      if(!current->free) 
      { 
       Block* current_prev = current->prev; 

       if(current_prev && current_prev->free) 
       { 
        Block* prev_prev = current_prev->prev; 
        int new_block_size = current_prev->size; 

        Block* moved_current = memmove(current_prev, current, sizeof(Block) + current->size); 

        if(!moved_current) 
        { 
         printf("couldn't move memory\n"); 
        } 
        else 
        { 
         Block* new_block = initBlock((((char*)moved_current) + sizeof(Block) + moved_current->size), new_block_size); 
         new_block->prev = moved_current; 
         new_block->next = moved_current->next; 

         moved_current->prev = prev_prev; 
         moved_current->next = new_block; 

         if(prev_prev) 
         { 
          prev_prev->next = moved_current; 
         } 

         current = moved_current; 
         continue; 
        } 
       } 
      } 

      current = current->next; 
     } 

     //Join Contiguous Blocks 
    } 
} 

initBlock işlevine çağrı sadece bir bellek adresi alır Blok yapısı gibi davranır, daha sonra doğru ve verilen boyuta boyut özelliğine serbest özelliğini ayarlar.

GCC derleyicisini -std = C99 bayrağı ile kullanıyorum.

+2

Tahsis edilen blokların sahibi, taşındıktan sonra ne yapacak? –

+0

@WeatherVane Şu anda, uni için bir görev için olduğu gibi sahibinin devam ettiğini gösteren işaretçilere sahip olmam şart değildir. Tahsislerin bir ara dizinine sahip olmak ve işaretçilerin devam etmesini sağlamak bana daha yüksek işaretler ekleyse de, alt işaretler için bir gereklilik değildir. –

+2

Defragger, kullanıcının bellek işaretleyicilerini nereye yerleştirdiğini bilmez, dolayısıyla bunları güncelleştiremezsiniz. Şüphesiz, kullanılmayan alanları yalnızca birleştirebilirsiniz. Sabit diski birleştirdiğinizde olduğu gibi, açık olan dosyalar taşınamaz. –

cevap

1

Bir çift bloğu değiştirdikten sonra sonraki bloğun prev alanını güncelleştirmiyorsunuz gibi görünüyor. Böylece bir sonraki bloğa geçtiğinizde ve önceki bloğun ücretsiz olup olmadığını kontrol ettiğinizde, çöp kutusuna erişirsiniz. Yukarıdaki else kısmen

if (newblock->next) 
    new_block->next->prev = new_block; 

gibi bir şey gerekiyor.

Diğer endişeler

  • senin bloklar hemen bitişik ve havuz içinde sırayla değilse bu kötü yaramazlık edecektir. Muhtemelen tüm havuzun tek bir bitişik anı bloğu olduğundan emin olabilirsiniz, ancak başka bir rutin bir şeyleri yeniden düzenlerse yine de problemlerle karşılaşabilirsiniz. Paranoyak programlama için, bu değişmezlerin ihlal edilmediğinden emin olmak için iddialara bağlı kalmak iyi bir fikirdir.
  • Bu işlemden sonra havuzdaki tüm dış işaretler çöp olacaktır
  • Tek boyutlu bloklarınız varsa (göründüğünüz gibi), en iyi verimsiz olan ve en kötü durumda olabilecek en düşük değere sahip olmayan işaretçiler alırsınız.
  • Havuzdaki işaretleyicileri içeren ilişkili bir sabit boyutlu "tutamaç" dizisi tanımladığınız gibi bir havuz için normaldir ve serbest olmayan bir bloğu her taşıdığınızda, işaretçiyi corrsponding kolu.Kulplar ayrıca hareketli blokları engelleyen "kilit" bayraklarına da sahip olabilirler - bu durumda bu bayrağı kontrol etmeniz ve sadece kilitlenmemiş blokları hareket ettirmeniz gerekir ve blokları hareket ettirdiğinizde bitişik olmayan bir bloğa geçmek isteyebilirsiniz. Bu, yukarıdaki ilk nokta ile başınızı belaya sokabilir.