Değişken Boyutlu Özdevinimli Saklama
Önceki Yazılım Verisine Saklama Alanı Ayrılması Sonraki
Değişken Boyutlu Özdevinimli Saklama
alloca işlevi, özdevimli ayrılan ama özdevinimli serbest bırakılan blokların yarı özdevimli bir bellek ayırma çeşidini destekler.
alloca ile bir bloğun ayrılması doğrudan doğruya yapılan bir eylemdir; istediğiniz kadar blok ayırabilir ve çalışma anında boyunu hesaplayabilirsiniz. Ancak serbest bırakma işlemi alloca işlevinin çağrıldığı işlevden çıkıldığında özdevinimli olarak gerçekleşir. Ayrılan alanı doğrudan doğruya serbest bırakmak için bir yol yoktur.
alloca işlevi stdlib.h başlık dosyasında bildirilmiştir ve bir BSD oluşumudur.
void *alloca
(size_t boyut)
işlev
Çağrıldığı işlevin yığıt çerçevesinde ayrılan boyut baytlık bir bloğun adresi ile döner.
alloca işlevini bir işlev çağrısının argümanı olarak kullanmayın, yoksa istenmeyen sonuçlar ortaya çıkabilir. Çünkü alloca için ayrılan yığıt alanı işlev argümanları için ayrılan alanın ortasındaki yığıtın üzerinde görünecektir. Örneğin, foo (x, alloca (4), y) gibi bir çağrı yapmayın.
alloca Örneği
alloca kullanılan bir örnek olarak, iki dizge argüman alıp bunları birleştirip bir dosya ismi elde eden ve bu dosyayı açtığında bu dosyaya bir tanıtıcı ile dönen, dosyayı açamazsa açamadığını belirtmek üzere -1 ile dönen bir işlev aşağıdadır:
int
open2 (char *str1, char *str2, int flags, int mode)
{
  char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1);
  stpcpy (stpcpy (name, str1), str2);
  return open (name, flags, mode);
}
Aşağıdaki örnekte ise aynı sonuç malloc ve free işlevleri ile elde edilmektedir:
int
open2 (char *str1, char *str2, int flags, int mode)
{
  char *name = (char *) malloc (strlen (str1) + strlen (str2) + 1);
  int desc;
  if (name == 0)
    fatal ("sanal bellek tükendi");
  stpcpy (stpcpy (name, str1), str2);
  desc = open (name, flags, mode);
  free (name);
  return desc;
}
Gördüğünüz gibi alloca ile işlem daha basittir. Ancak alloca işlevinin getirileri kadar götürüleri de vardır.
alloca İşlevinin Getirileri
alloca işlevinin malloc işlevine tercih edilmesindeki sebepler:
  • alloca kullanılarak çok küçük bir alan işe yaramaz hale gelir ve işlev çok hızlıdır. (GNU C derleyicisi içinde açık kodludur.)
  • alloca farklı blok boyları için ayrı havuzlar oluşturmadığından, farklı boylardaki bloklar başka boylarda bloklar oluşturmak için yeniden kullanılabilir. alloca bellek parçalanmasına sebep olmaz.
  • Yerel olmayan çıkışlar longjmp alloca işlevini çağıran işlevden de çıkışa sebep olacağından alloca ile ayrılan alan özdevinimli olarak serbest bırakılır. Bu, alloca işlevinin kullanılması için en önemli sebeptir.
    Bunu örnekleyecek olursak, open gibi başarılı olduğunda bir dosya tanıtıcı döndüren ama başarısız olduğunda dönmeyen open_or_report_error isimli bir işleviniz olsun. Dosya açılamazsa bir hata iletisi bassın ve longjmp kullanarak yazılımınızın komut seviyesine geçsin. Önceki örnekteki open2 işlevini bu işlevi kullanacak şekilde değiştirelim:
    int
    open2 (char *str1, char *str2, int flags, int mode)
    {
      char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1);
      stpcpy (stpcpy (name, str1), str2);
      return open_or_report_error (name, flags, mode);
    }
    
    alloca işlevinin çalışma şeklinden dolayı, ayırdığı bellek bir hata oluşsa bile serbest bırakılır ve bunun için ek bir çaba gerekmez.
    Karşılaştıma için, open2 işlevinin önceki tanımı (malloc ve free kullanılan) bu amaç için değiştirildiğinde bir bellek artığı oluşacaktı. Hatta, siz bunu düzeltmek için her değişikliği yapmaya razı olsanız bile, bunu yapmanın daha kolay bir yolu yoktur.
alloca İşlevinin Götürüleri
alloca işlevinin malloc ile karşılaştırıldığında bazı götürüleri vardır:
  • Makinenin sağladığından daha fazla bellek ayırmaya kalkarsanız temiz bir hata iletisi almazsınız. Bunun yerine bir sonsuz döngünün oluşturduğu gibi, olası bir bölütleme karışıklığından dolayı bir ölümcül sinyal alırsınız.
  • Bazı GNU dışı sistemlerde daha az taşınabilir olduğundan alloca desteği bulunmayabilir. Yine de bazı sistemlerdeki bu eksikliği gidermek için yazılmış daha yavaş bir taklidi C'de vardır.
GNU C Değişken Boyutlu Dizileri
GNU C'de alloca kullanımı yerine birçok durumda bir değişken boyutlu dizi kullanılabilir. Önceki örneklerdeki open2 işlevini bu şekilde değiştirelim:
int open2 (char *str1, char *str2, int flags, int mode)
{
  char name[strlen (str1) + strlen (str2) + 1];
  stpcpy (stpcpy (name, str1), str2);
  return open (name, flags, mode);
}
Ancak çeşitli sebeplerle, alloca daima bir değişken boyutlu diziye eşdeğer değildir:
  • Bir değişken boyutlu dizinin bellek alanı, dizi isminin etki alanının sonunda serbest bırakılır. alloca ile ayrılan alan ise işlev sonuna kadar kalır.
  • alloca işlevi her yinelemede ek bir blok ayırmak üzere bir döngü içinde kullanılabilir. Bu değişken boyutlu dizilerle mümkün değildir.
Not
alloca ile değişken boyutlu dizileri aynı işlevde karışık kullanırsanız, bir değişken boyutlu dizinin bildirildiği etki alanının çıkması, bu etki alanının çalışması sırasında alloca ile ayrılmış tüm blokların serbest bırakılmasına sebep olur.
Önceki Üst Ana Başlık Sonraki
Yığınaklar (Obstacks) Başlangıç Veri Bölütünün Boyunun Değiştirilmesi
Bir Linux Kitaplığı Sayfası