SORU
13 HAZİRAN 2014, Cuma


Neden `ücretsiz` C bayt sayısını serbest almaz?

Sadece açık: biliyorum malloc free uygulandığını C kütüphanesi, genellikle ayırır parçalar bellekten işletim sistemi ve kendi yönetimine parsellemek küçük sürü bellek kullanımı ve tutar parça sayısı bayt ayrılmış. Bu soru How does free know how much to free değildir.

Daha doğrusu, free ilk etapta bu şekilde yapıldı neden bilmek istiyorum. Olmak düşük seviyeli bir dil, bence olur gayet mantıklı isteyin bir C programcısı için takip edin sadece ne kadar bellek ayrılmış ama ne kadar (aslında, ben sık I sonunda numarasını izlemek için bayt malloced neyse). Ayrıca aklıma gelmişken açıkça veren bayt sayısı free olabilir izin vermek için bazı performans optimizasyonu, örneğin bir ayırıcı vardır ayrı havuzları için farklı ayırma boyutlarda olacağını tespit etme, hangi restorana sadece bakarak giriş bağımsız değişkenleri, ve orada olacak daha az yer Tepegöz genel olarak.

Kısacası, neden malloc free DAHİLİ olarak ayrılan bayt sayısını takip etmesi gerekir, böyle mi yarattı? Sadece tarihi bir tesadüf mü?

Küçük bir düzenleme: Bir kaç kişi gibi puan vermiş "eğer sana ayrılan ne farklı miktarda serbest bırakırsan ne". Hayal benim API sadece biri tam olarak ayrılan bayt sayısını ücretsiz gerektirir olabilir; daha fazla veya daha az boşaltma sadece veya uygulama tanımlı İK olabilir. Diğer olasılıklar hakkında tartışma vazgeçirmek için, ama istemiyorum.

CEVAP
14 HAZİRAN 2014, CUMARTESİ


-Bağımsız değişken free(void *) (sunulan Unıx V7) sahip olan başka bir büyük avantajı daha önce iki parametre mfree(void *, size_t) görmedim burada bahsedilen: bir bağımsız değişken free Her ölçüde kolaylaştırırdiğerAPI yığın bellek ile çalışır. Örneğin, eğer free gerekli büyüklükte bir bellek bloğu, strdup ki bir şekilde dönmek iki değer (işaretçi boyutu) yerine bir (işaretçi) ve C yapar çok değer verir çok daha hantal daha tek değer döndürür. char *strdup(char *) yerine char *strdup(char *, size_t *) yoksa struct CharPWithSize { char *val; size_t size}; CharPWithSize strdup(char *) yazmak zorunda kalırız. (Günümüzde bu ikinci seçeneği oldukça cazip görünüyor, NULL sonlandırılmış bir dize ** 31, ama geriye dönüp baktığımda bu konuşma olduğunu biliyoruz çünkü. Geri 70, C Basit olarak dizeleri işlemek için yeteneği char * aslında*.* 32) kabul edildi Artı, sadece sistem ya da kullanıcı tanımlı her fonksiyon etkiler yığın bellek ayırır, bu sorundan muzdarip olan strdup değil.

Erken Unix tasarımcılar çok zeki insanlar ve yapacak çok nedenimiz var ... free iyidir mfree yani Kısacası bence cevabın sorusu olduğunu fark ettim ve bu sistemi buna göre tasarlanmıştır. Bu kararı verdikleri anda kafalarının içinde neler olup bittiğini herhangi bir doğrudan kayıt bulacağından şüpheliyim. Ama hayal edebiliriz.

V6 Unıx, iki bağımsız değişken mfree ile çalıştırmak için C uygulamaları yazma gibi yap. Tamam bu zamana kadar idare ettik, ama bu işaretçi boyutları izlemek ve programlarınızı 33 ** ve öbek ayrılmış değişkenler daha fazla ve daha fazla kullanım gerektiren bir güçlük daha fazla oluyor. Ama sonra parlak bir fikir var: size_tBu s kopyalamak yerine her zaman, sadece doğrudan ayrılan bellek içinde: boyutu zula bazı yardımcı fonksiyonlar yazabilirsiniz

void *my_alloc(size_t size) {
    void *block = malloc(sizeof(size)   size);
    *(size_t *)block = size;
    return (void *) ((size_t *)block   1);
}
void my_free(void *block) {
    block = (size_t *)block - 1;
    mfree(block, *(size_t *)block);
}

Ve daha fazla kod bu yeni fonksiyonları kullanarak yazmak, daha şahane görünüyorlar. Sadece kod yazmak daha kolay yaparlar, onlarayrıcakodunuzu olundaha hızlısık sık bir araya gelmez olan iki şey! size_tkopyalama için CPU yükü eklendi ve kayıtları dökmek için anlamı olan bir yerde, üzerinde daha sık (esp. nin bu geçirmeden önce ekstra işlev bağımsız değişkenleri) ve harcanan bellek, iç içe geçmiş işlev çağrıları sık sık size_t yığın çerçeveler içinde farklı depolanan birden çok kopyasını neden olacağından (). Yeni sistem, hala hafıza size_t, ama yalnızca bir kez depolamak için harcamak zorunda, ve o hiç bir yere kopyalanmasını. Bu küçük verimlilik gibi görünebilir, ama RAM 256 KB ile high-end makineleri hakkında konuşuyoruz unutmayın.

Bu seni mutlu ediyor! Bir sonraki Unıx sürümü üzerinde çalışan sakallı adamlar ile harika hile paylaşmak, ama onları mutlu etmez, onları üzüyor. Bakın, sadece bu sürecin ekleme bir sürü yeni işlevler gibi strdup, ve onlar fark bu insanları kullanarak cool trick mümkün olmayacaktır kendi içinde yeni işlevler, çünkü onların yeni fonksiyonlar kullanma hantal işaretçi boyutu API. Ve sonra o strdup(char *) yazdığınız her programda kendini işlevi iyi yazmak için, sistem sürümünü kullanmak için güçlü olmak yerine olacak farkındasın, çünkü seni çok üzer.

Ama bekleyin! Bu 1977 ve uyumluluk bir 5 yıl daha icat edilmemiş olacak. geriye! Ve kimse ciddi ayrıca aslındakullanırbu "Unıx" off-renk adıyla şey. karanlık İlk baskısı K&R yolda geliyor, yayımcı, ama bu sorun değil. hemen ilk sayfada, "C sağlar herhangi bir işlem için anlaşma doğrudan kompozit nesneleri gibi karakter dizeleri... hiçbir yığın...". Tarih, string.h malloc bu noktada satıcı uzantıları (!). Sakallı Adam #1, seviyoruz ancak onları değiştirebiliriz; neden olmak zor senin ayırıcısı ilan yok . gösteriyor yani ^em>resmiayırıcı?

Birkaç gün sonra, Sakallı Adam #2 yeni API görür ve hey, bekle, bu daha iyi, ama yine de ayırma başına bütün bir kelime boyutunu saklamak harcama olduğunu söylüyor. Küfür etmek bir sonraki şey olarak görüyor. Herkes deli gibi ona baktı, çünkü başka ne yapabilirsin? O gece geç kalır ve icat yeni bir ayırıcı bilmeyen deposu boyutunu, ama yerine varır üzerinde sinek gerçekleştirerek kara büyü bitshifts işaretçiyi değer ve swapları bunu yaparken tutulması yeni API yerleştirin. Yeni API kimse anahtarı bildirimleri, ama ertesi sabah derleyici  daha az RAM kullanan bir duyuru yapmak anlamına gelir.

Ve şimdi herkes mutlu olsun: sizin daha kolay ve daha hızlı kod yazmak, Sakallı Adam #1 alır yazmak için güzel bir basit strdup bu insanlar aslında kullanmak ve Sakallı Adam #2 -- kendine güvenen bunu hak etti onun tutmak için biraz geri gidiyor messing around with quines. Bu gemi!

Ya da en azından, o kadarolabiliroldu.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • CrazyMan

    CrazyMan

    14 Mayıs 2008
  • Epic Tutorials for iPhone, iPad and iOS

    Epic Tutoria

    18 EYLÜL 2011
  • Pepsi

    Pepsi

    1 Kasım 2005