Malloc ve calloc arasındaki fark nedir?


780

Doing arasındaki fark nedir:

ptr = (char **) malloc (MAXELEMS * sizeof(char *));

veya:

ptr = (char **) calloc (MAXELEMS, sizeof(char*));

Malloc üzerinde calloc kullanmak ne zaman iyi bir fikirdir?



8
C de yukarıdakileri daha genel olarak yazabilirsiniz:ptr = calloc(MAXELEMS, sizeof(*ptr));
chqrlie


2
@ddddavidee Ben de o blogda çok fazla cevaptan memnun kaldıktan sonra buldum. Nathaniel J. Smith analizi için 100+ SO puanını hak ediyor.
lifebalance

Yanıtlar:


851

calloc() sıfır sıfırlanmış bir tampon verirken malloc() belleği başlatılmaz.

Büyük ayırmalar için, callocgenel işletim sistemleri altındaki uygulamaların çoğu işletim sisteminden bilinen sıfırlanmış sayfalar alır (örneğin POSIX mmap(MAP_ANONYMOUS)veya Windows aracılığıyla VirtualAlloc), böylece bunları kullanıcı alanına yazmanıza gerek kalmaz. Bu normalden mallocişletim sisteminden daha fazla sayfa alır; callocsadece işletim sisteminin garantisinden yararlanır.

Bu, callocbelleğin yine de "temiz" ve tembel olarak tahsis edilebileceği ve yazma sırasında kopyalamanın sistem genelinde paylaşılan bir fiziksel sıfır sayfasına eşleştirilebileceği anlamına gelir . (Sanal belleğe sahip bir sistem olduğunu varsayarsak.)

Bazı derleyiciler malloc + memset'i (0) sizin için calloc olarak optimize edebilir, ancak belleğin olarak okunmasını istiyorsanız calloc'u açıkça kullanmalısınız 0.

Belleği yazmadan önce okumayacaksanız malloc, işletim sisteminden yeni sayfalar almak yerine (muhtemelen) size dahili boş listesinden kirli bellek verebilmesi için kullanın. (Veya küçük bir tahsis için serbest listede bir bellek bloğunu sıfırlamak yerine).


Katıştırılmış uygulamaları, işletim sistemi yoksa kendisini sıfır belleğe callocbırakabilir callocveya işlemler arasında bilgi sızıntılarını durdurmak için sayfaları sıfırlayan süslü bir çok kullanıcılı işletim sistemi değildir.

Gömülü Linux'ta, mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS)çok kullanıcılı bir sistemde güvensiz olduğu için yalnızca bazı gömülü çekirdekler için etkinleştirilen malloc olabilir .


224
* Ayırma varyantları oldukça anımsatıcıdır - temizle ayır, bellek ayır, yeniden ayır.
Cascabel

43
Ayrılan alanda kullandığınız her şeyi ayarlayacaksanız malloc () kullanın. Verilerin bazı bölümlerini başlatılmayacaksanız calloc () işlevini kullanın - ve ayarlanmamış parçaların sıfırlanması yararlı olacaktır.
Jonathan Leffler

268
callocişletim sistemi hızlandırmak için bazı hileler yapabildiğinden, mutlaka daha pahalı değildir. FreeBSD'nin boş bir CPU zamanı aldığında, sadece etrafta dolaşan ve ayrılmış bellek bloklarını sıfırlayan basit bir işlemi çalıştırmak için kullandığını ve blokları bir bayrakla işaretlediğini biliyorum. Yani bunu yaptığınızda calloc, önce bu gibi önceden sıfırlanmış bloklardan birini bulmaya çalışır ve sadece size verir - ve büyük olasılıkla bir tane bulur.
Pavel Minaev

28
Kodunuz varsayılan olarak sıfır girişli tahsisler sonucunda "daha güvenli" olursa, malloc veya calloc kullansanız bile kodunuzun yeterince güvenli olmadığını hissetme eğilimindeyim. Malloc kullanmak verilerin başlatılması gerektiğini gösteren iyi bir göstergedir - calloc'u sadece bu 0 baytın gerçekten anlamlı olduğu durumlarda kullanırım. Ayrıca calloc'un karakter olmayan türler için düşündüklerinizi yapması gerekmediğini unutmayın. Artık hiç kimse gerçekten tuzak temsili kullanmıyor ya da IEEE olmayan şamandıralar, ancak kodunuzun olmadığı zaman gerçekten taşınabilir olduğunu düşünmek için bir bahane yok.
Steve Jessop

18
@SteveJessop "Daha güvenli" doğru kelime değil. Bence "Deterministik" daha iyi bir terimdir. Zamanlamaya ve veri dizilerine bağlı arızalara sahip olmaktan ziyade daha belirleyici olan kod, arızaları izole etmek daha kolay olacaktır. Calloc bazen açık bir başlatmaya karşı bu determinizmi elde etmenin kolay bir yoludur.
dennis

362

Daha az bilinen bir fark, Linux gibi iyimser bellek tahsisine sahip işletim sistemlerinde, döndürülen işaretçinin mallocprogram gerçekten dokunana kadar gerçek bellek tarafından desteklenmemesidir.

callocgerçekten belleğe dokunuyor (üzerine sıfırlar yazıyor) ve böylece işletim sisteminin tahsisi gerçek RAM (veya takas) ile desteklediğinden emin olacaksınız. Bu yüzden malloc'dan daha yavaştır (sadece sıfırlamakla kalmaz, işletim sistemi de diğer işlemleri değiştirerek uygun bir bellek alanı bulmalıdır)

Malloc'un davranışı hakkında daha fazla tartışma için bu SO sorusuna bakınız.


49
callocsıfır yazmanıza gerek yok. Tahsis edilen blok çoğunlukla işletim sistemi tarafından sağlanan yeni sıfır sayfadan oluşuyorsa, bu sayfalara dokunulmaz. Bu, elbette, callocgenel bir kütüphane işlevi yerine işletim sistemine ayarlanmalıdır malloc. Ya da bir uygulayıcı, callocsıfırlamadan önce her bir kelimeyi sıfıra karşı kıyaslayabilir. Bu hiçbir zaman kazandırmaz, ancak yeni sayfaların kirlenmesini önler.
R. .. GitHub DURDURMAK BUZ

3
@R .. ilginç not. Fakat pratikte, bu tür uygulamalar vahşi doğada var mı?
Isak Savo

10
Tüm dlmallocbenzeri uygulamalar , yeni anonim sayfalar (veya eşdeğeri) kullanılarak memsetyığının elde edilip edilmediğini atlar mmap. Genellikle bu tür tahsis 256k ya da daha büyük büyük parçalar için kullanılır. Kendi başıma sıfır yazmadan önce sıfıra karşı karşılaştırma yapan herhangi bir uygulama bilmiyorum.
R. .. GitHub DURDURMA BUZA YARDIMCI OLACAKLAR

1
omallocayrıca atlar memset; callocuygulama tarafından kullanılmayan sayfalara (sayfa önbelleği) dokunmak gerekmez. Yine de, son derece ilkel callocuygulamalar farklıdır.
mirabilos

10
glibc'nin calloc, işletim sisteminden yeni bir bellek alıp almadığını kontrol eder. Eğer öyleyse, yazması gerekmediğini bilir, çünkü mmap (..., MAP_ANONYMOUS) zaten sıfırlanmış olan belleği döndürür.
Peter Cordes

112

Sıklıkla gözden kaçan bir avantaj, calloc(uygun uygulamaların) sizi tamsayı taşması güvenlik açıklarına karşı korumaya yardımcı olmasıdır. Karşılaştırmak:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

vs.

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

Birincisi, küçük bir ayırmaya ve daha sonra countdaha büyük bir arabellek taşmasına neden olabilir.SIZE_MAX/sizeof *bar . İkincisi, bu durumda büyük bir nesne oluşturulamadığı için otomatik olarak başarısız olur.

Tabii ki, taşma olasılığını görmezden gelen uygun olmayan uygulamalar için uyanık olmanız gerekebilir ... Bu, hedeflediğiniz platformlar için bir endişe ise, taşma için yine de manuel bir test yapmanız gerekecektir.


17
Görünüşe göre aritmetik taşma 2002'de OpenSSH deliğine neden oldu. Bellekle
Philip P.

4
@KomradeP .: İlginç. Ne yazık ki bağladığınız makalenin başında yanlış bilgi var. İle, örneğin charbir değil bir içerisine sonucu geri atama bir taşma daha ziyade bir uygulama tanımlı dönüşüm charnesne.
R .. GitHub BUZA YARDIMCI DURDUR

Muhtemelen sadece örnekleme amaçlıdır. Çünkü derleyici bunu zaten optimize edecek gibi görünüyor. Benimki bu girişimi derliyor: 1. itin.
Philip P.

1
@ tristopia: Mesele, kodun tüm uygulamalarda kullanılabilir olması değil, ek varsayımlar olmadan yanlış olması ve dolayısıyla doğru / taşınabilir kullanım olmamasıdır.
R .. GitHub BUZA YARDIMCI DURDUR

3
@ tristopia: Düşünme biçiminiz " size_t64-bit ise sorun değil" ise, bu güvenlik hatalarına yol açacak kusursuz bir düşünce biçimidir. size_tboyutlarını temsil eder ve 32 bit numarası ve bir keyfi ürünü düşünmek için hiçbir neden yok soyut bir türüdür size_t(not: sizeof *barprensipte 64-bit C uygulanmasına ilişkin 2'den büyük ^ 32 olabilir!) içinde uyuyor size_t.
R .. GitHub BUZA YARDIMCI DURDUR

37

Belgeler, calloc'u belleği sıfırla başlatan malloc gibi görünür; bu birincil fark değil! Calloc fikri bellek tahsisi için yazma üzerine kopyalama semantiğini kullanmaktır. Calloc ile bellek ayırdığınızda, hepsi sıfıra başlatılan aynı fiziksel sayfaya eşlenir. Ayrılan belleğin sayfalarından herhangi biri fiziksel bir sayfaya yazıldığında ayrılır. Bu genellikle BÜYÜK karma tabloları yapmak için kullanılır, örneğin karma boş bölümleri fazladan bellek (sayfalar) tarafından desteklenmediğinden; bunlar mutlu bir şekilde sıfırdan başlatılmış tek bir sayfaya işaret ederler, bunlar süreçler arasında bile paylaşılabilir.

Sanal adrese herhangi bir yazma bir sayfaya eşlenir, bu sayfa sıfır sayfaysa, başka bir fiziksel sayfa tahsis edilir, sıfır sayfa buraya kopyalanır ve kontrol akışı istemci işlemine döndürülür. Bu bellek eşleme dosyaları aynı şekilde çalışır, sanal bellek, vb çalışır .. çağrı kullanır.

İşte konu hakkında bir optimizasyon hikayesi: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/


26

Ayrılan bellek bloğunun boyutu arasında fark yoktur. callocbellek bloğunu tamamen sıfır bitlik fiziksel bir desenle doldurur. Pratikte, tahsis edilen bellek bloğunda bulunan nesnelerin callocdeğişmez değerle başlatılır gibi başlangıç ​​değerine sahip olduğu 0, yani tamsayıların 0kayan noktalı değişkenlerin - değerinin 0.0, işaretçilerin - uygun boş-işaretçi değerine sahip olması gerektiği varsayılır. , ve bunun gibi.

Bilgiçliksel bakış açısından, calloc(ve aynı zamanda memset(..., 0, ...)) sadece tip nesnelerini (sıfırlarla) doğru şekilde başlatması garanti edilir unsigned char. Diğer her şeyin doğru şekilde başlatıldığı garanti edilmez ve tanımlanmamış davranışa neden olan tuzak gösterimi içerebilir . Başka bir deyişle, unsigned charyukarıda belirtilen tüm sıfır-bitli patterm dışında herhangi bir tür geçersiz bir değeri, tuzak temsilini temsil edebilir.

Daha sonra, Teknik Düzeltme-C99 standardından birinde, davranış tüm tamsayı türleri için tanımlanmıştır (bu anlamlıdır). Yani resmi olarak, mevcut C dilinde yalnızca calloc(ve memset(..., 0, ...)) ile tamsayı türlerini başlatabilirsiniz . Genel durumda başka bir şey başlatmak için kullanılması, C dili açısından tanımlanmamış davranışa yol açar.

Pratikte, callochepimizin bildiği gibi çalışır :), ancak (yukarıdakileri göz önünde bulundurarak) kullanmak isteyip istemediğiniz size bağlıdır. Şahsen bundan tamamen kaçınmayı tercih ediyorummalloc onun yerine ve kendi başlatmamı .

Son olarak, bir diğer önemli ayrıntı, callocson blok boyutunu dahili olarak hesaplamak için eleman boyutunu eleman sayısıyla çarparak yapılmasıdır. Bunu yaparken, callocolası aritmetik taşmaya dikkat etmelisiniz. İstenen blok boyutu doğru bir şekilde hesaplanamazsa, ayırma başarısız olur (boş gösterici). Bu arada, mallocsürümünüz taşma izlemeye çalışmaz. Taşma durumunda bir miktar "öngörülemeyen" bellek ayıracaktır.


"Bir başka önemli detay" paragrafına göre: bu memset(p, v, n * sizeof type);bir sorun n * sizeof typeyaratıyor çünkü taşma olabilir. Sanırım for(i=0;i<n;i++) p[i]=v;sağlam kod için bir döngü kullanmam gerekecek .
chux - Monica adlı kişiyi geri yükle

Kodun, bir uygulamanın all-bits-zero'u boş bir işaretçi olarak kullanması gerektiğini (başka bir şekilde derlemeyi reddetmesi) gerektireceği standart bir yöntem varsa yararlı olacaktır, çünkü diğer boş işaretçi gösterimlerini kullanan uygulamalar vardır, ancak bunlar nispeten nadir; işaretçiler dizilerini başlatmak için calloc () veya memset kullanabiliyorsa bu tür uygulamalarda çalışması gerekmeyen kod daha hızlı olabilir.
supercat

@chux Resim, bir dizi halinde nbir eleman boyutuna sahip olduğu elemanları bulunmaktadır sizeof type, o zaman n*sizeof typetaşması nedeniyle herhangi bir nesnenin en büyük boyutu daha az olmalıdır olabilir SIZE_MAX.
12431234123412341234123

@ 12431234123412341234123 <= dizi boyutu hakkında doğru SIZE_MAX, ancak burada diziler yok. İşaretçiden döndürülen işaretçi calloc(), aşılmamış bellek miktarını aşıyor olabilir SIZE_MAX. Birçok uygulamalar için 2 args ürünü sınırladık calloc()için SIZE_MAXhenüz C talent sınırlama getirmez.
chux - Monica adlı kişiyi geri yükle

21

Bir makaleden calloc ile eğlenceli Benchmarking () ve sıfır sayfalarda üzerine Georg Hager Blogu

Calloc () kullanarak bellek ayırırken, istenen bellek miktarı hemen ayrılmaz. Bunun yerine, bellek bloğuna ait tüm sayfalar, bazı MMU sihirleriyle tüm sıfırları içeren tek bir sayfaya bağlanır (aşağıdaki bağlantılar). Bu tür sayfalar yalnızca okunursa (karşılaştırmanın orijinal sürümündeki b, c ve d dizileri için geçerliyse) veriler, elbette önbelleğe uyan tek sıfır sayfasından sağlanır. Belleğe bağlı döngü çekirdekleri için çok fazla. Bir sayfa yazılırsa (nasıl olursa olsun) bir hata oluşursa, “gerçek” sayfa eşlenir ve sıfır sayfa belleğe kopyalanır. Buna yazma üzerine kopyalama, iyi bilinen bir optimizasyon yaklaşımı denir (hatta C ++ derslerimde birçok kez öğrettim). Daha sonra,


bağlantı nerede?
Rupesh Yadav.

2
ilk cevap satırı Georg Hager'ın Blog'una bağlantı içerir
Ashish Chavan

11

callocgenellikle malloc+memset0

Özellikle aşağıdaki malloc+memsetgibi bir şey yaparken açıkça kullanmak genellikle biraz daha iyidir :

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

Bu daha iyidir çünkü sizeof(Item)derleyici tarafından derleme zamanında bilinir ve derleyici çoğu durumda sıfır bellek için mümkün olan en iyi talimatlarla değiştirir. Öte yandan memset, gerçekleşiyorsa calloc, tahsisin parametre boyutu callockodda derlenmez ve memsetgenellikle genellikle çağrılır, uzun sınıra kadar bayt-bayt dolgusu yapmak için kod içerecek şekilde doldurulur. sizeof(long)parçalar halinde bellek ve son olarak kalan boşluğu bayt-byte doldurur. Ayırıcı, bazılarını çağıracak kadar akıllı olsa bile aligned_memset, hala genel bir döngü olacaktır.

Dikkate değer bir istisna, çok büyük bir bellek yığınının (bazı power_of_two kilobayt) malloc / calloc işlemini gerçekleştirmenizdir, bu durumda tahsis doğrudan çekirdekten yapılabilir. İşletim sistemi çekirdekleri genellikle güvenlik nedeniyle verdikleri tüm belleği sıfırlayacağından, yeterince akıllı calloc ek sıfırlama ile geri döndürebilir. Yine - sadece küçük olduğunu bildiğiniz bir şeyi ayırıyorsanız, malloc + memset performans açısından daha iyi olabilirsiniz.


Sistem kitaplığındaki bir işlevselliğin genel bir uygulamasının, kullanıcı kodundaki aynı işlemden daha hızlı olması gerekmediğini hatırlatmak için +1.
Patrick Schlüter

1
Daha calloc()yavaş yapan ikinci bir nokta daha vardır malloc(): boyut için çarpma. malloc () genellikle bir derleme zaman sabitine sahip olacakken, calloc()genel bir çarpma ( size_t64 bit ise çok pahalı 64 bit * 64 bit = 64 bit işlem) kullanmak gerekir.
Patrick Schlüter

4
glibc calloc, döndürülen yığının en verimli şekilde nasıl temizleneceğine karar vermek için bazı akıllılara sahiptir, örneğin bazen sadece bir kısmının temizlenmesi gerekir ve ayrıca 9 * boyutuna (size_t) kadar açık bir açıklık. Bellek bellektir, bir seferde 3 bayt temizlemek daha hızlı olmayacaktır, çünkü daha sonra tutmak için kullanacaksınız struct foo { char a,b,c; };. callocher zaman tüm bölgeyi temizleyecekseniz malloc+ ' dan her zaman daha iyidir . boyut * öğelerinde de int taşması için dikkatli ama etkili bir denetime sahiptir. memsetmalloccalloc
Peter Cordes

8

Fark 1:

malloc() genellikle bellek bloğunu tahsis eder ve bellek segmentidir.

calloc() bellek bloğunu ayırır ve tüm bellek bloğunu 0 olarak başlatır.

Fark 2:

Eğer düşünürsek malloc()sözdizimi, sadece 1 argüman alacak. Aşağıdaki örneği inceleyin:

data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );

Örn: int türü için 10 blok bellek ayırmak istiyorsanız,

int *ptr = (int *) malloc(sizeof(int) * 10 );

Eğer düşünürsek calloc()sözdizimi, bu 2 argüman alacak. Aşağıdaki örneği inceleyin:

data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

Örn: int türü için 10 blok bellek ayırmak ve bunların tümünü SIFIRLA başlatmak istiyorsanız,

int *ptr = (int *) calloc(10, (sizeof(int)));

Benzerlik:

Her ikisi de malloc()ve calloc()döküm türü değilse varsayılan olarak geçersiz * döndürür.!


Ve data_type ve cast_type'i neden farklı tutuyorsunuz?
satıldı

7

İki fark vardır.
Birincisi, argümanların sayısıdır. iki bağımsız değişkene ihtiyaç malloc()duyarken, tek bir bağımsız değişken alır (bayt cinsinden bellek gerekir) calloc().
İkinci olarak, malloc()ayrılan bellek, süre başlatılmaz calloc()SIFIR başlatır ayrılan belleği.

  • calloc()bir bellek alanı tahsis ederse, uzunluk parametrelerinin ürünü olacaktır. callocbelleği SIFIR ile doldurur ve ilk bayta bir işaretçi döndürür. Yeterli yer bulamazsa bir NULLişaretçi döndürür .

Sözdizimi: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); ieptr_var=(type *)calloc(n,s);

  • malloc()REQUSTED SIZE belleğinin tek bir bloğunu ayırır ve ilk bayta bir işaretçi döndürür. Gerekli bellek miktarını bulamazsa, boş gösterici döndürür.

Kullanımı: sırasında işlevi, bayt sayısı tahsis etmektir bir bağımsız değişken almak fonksiyon elemanlarının sayısı olmak, bir, iki bağımsız değişken ve diğer bayt sayısı bu elemanların her biri için tahsis etmek için olmak. Ayrıca, ayrılmış alanı sıfırlar, ilk sırada sıfırlar .ptr_var=(cast_type *)malloc(Size_in_bytes);malloc()calloc()calloc()malloc()


6

calloc()Deklare edilmediği fonksiyon <stdlib.h>başlığının üzerinde birkaç avantajı sunmaktadır malloc()fonksiyonu.

  1. Belleği belirli bir boyuttaki birkaç öğe olarak ayırır ve
  2. Tahsis edilen belleği, tüm bitlerin sıfır olması için başlatır.

6

malloc()ve calloc()C standart kitaplığından dinamik bellek ayırmaya izin veren işlevlerdir, yani her ikisi de çalışma zamanı sırasında bellek ayırmaya izin verir.

Prototipleri aşağıdaki gibidir:

void *malloc( size_t n);
void *calloc( size_t n, size_t t)

Bu ikisi arasında temel olarak iki fark vardır:

  • Davranış: malloc()bir bellek bloğunu başlatmadan ayırır ve bu bloktaki içeriği okumak çöp değerlerine neden olur. calloc()Öte yandan, bir bellek bloğu tahsis eder ve sıfırlara başlatır ve bu bloğun içeriğini okumak sıfırlarla sonuçlanır.

  • Sözdizimi: malloc()1 bağımsız değişken alır (ayrılacak boyut) ve calloc()iki bağımsız değişken alır (ayrılacak blok sayısı ve her bloğun boyutu).

Her ikisinden de dönüş değeri, başarılıysa, ayrılan bellek bloğunun bir göstergesidir. Aksi takdirde, bellek ayırma hatasını belirten NULL döndürülür.

Misal:

int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));

Aynı işlevi olarak calloc()kullanılarak elde edilebilir malloc()ve memset():

// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 

Not malloc()tercihen üzerinde kullanıldığında calloc()daha hızlı beri. Değerlerin sıfırdan başlatılması isteniyorsa calloc()bunun yerine kullanın.


5

Henüz belirtilmeyen bir fark: boyut sınırı

void *malloc(size_t size)en fazla kadarını ayırabilir SIZE_MAX.

void *calloc(size_t nmemb, size_t size);hakkında tahsis edebilir SIZE_MAX*SIZE_MAX.

Bu yetenek, doğrusal adreslemeli birçok platformda sıklıkla kullanılmaz. Bu tür sistemler, sınırlama calloc()ile nmemb * size <= SIZE_MAX.

512 baytlık bir tür düşünün disk_sectorve kod çok sayıda sektör kullanmak istiyor . Burada kod yalnızca SIZE_MAX/sizeof disk_sectorsektörlere kadar kullanılabilir .

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

Daha da büyük bir ayırmaya izin veren aşağıdakileri göz önünde bulundurun.

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

Şimdi böyle bir sistem böyle büyük bir tahsis sağlayabiliyorsa başka bir konudur. Bugün çoğu olmayacak. Yine de, SIZE_MAX65535 iken uzun yıllar oldu. Moore yasası göz önüne alındığında , bunun yaklaşık 2030'luk SIZE_MAX == 4294967295100 GB'lık bazı bellek modelleri ve bellek havuzları ile gerçekleşeceğinden şüpheleniliyor .


2
Genellikle size_t, bir programın işleyebileceği en büyük nesnenin boyutunu tutabilecektir. Size_t değerinin 32 bit olduğu bir sistemin, 4294967295 bayttan daha büyük bir ayırma işlemini gerçekleştirmesi olası değildir ve bu boyuttaki ayırmaları işleyebilecek bir sistemin neredeyse kesinlikle size_t32 bitten daha büyük olmasını sağlar. Tek soru, callocürünü aşan değerlerle kullanmanın , SIZE_MAXbir işaretçiyi daha küçük bir ayırmaya döndürmek yerine sıfır elde etmeye güvenip güvenemeyeceğidir.
supercat

Genellemeniz konusunda anlaşın , ancak C spesifikasyonu calloc()aşan tahsislere izin veriyor SIZE_MAX. Geçmişte 16 bit ile oldu size_tve bellek ucuzlamaya devam ettikçe, yaygın olmasa bile ilerlemesinin hiçbir nedeni göremiyorum .
chux - Monica'yı geri yükle

1
C Standardı, kodun boyutu aşan bir ayırma istemesini mümkün kılar SIZE_MAX. Kesinlikle böyle bir tahsisin başarılı olabileceği herhangi bir koşul olmasını gerektirmez; Bu tür tahsisleri gerçekleştiremeyen uygulamaların geri dönmesi gerektiğini belirtmenin özel bir yararı olmadığından emin değilim NULL(özellikle bazı uygulamaların mallochenüz taahhüt edilmemiş ve kod gerçekten kullanmaya çalıştığında boşluğa dönüş işaretlerinin olması yaygın olduğu göz önüne alındığında) o).
supercat

Ayrıca, geçmişte mevcut adresleme aralığı temsil edilebilir en büyük tamsayıyı aşan sistemlerin olabileceği yerlerde, milyarlarca gigabaytlık bir depolama kapasitesi gerektireceğinden, bunun bir daha gerçekleşmesi için gerçekçi bir olasılık görmüyorum. Moore Yasası tutulmaya devam etse bile, 32 bitin yeterli olduğu noktadan 64 bitin yeterli olduğu noktaya gelmek, 16 bitin yeterli olduğu noktadan 32 bitin olmadığı noktaya kadar iki kat daha fazla zaman alacaktır. 't.
supercat

1
Neden 4G aşırı tek tahsisini kalabileceği bir uygulama değil tanımlarsınız size_tiçin uint64_t?
supercat

2

Blok sayısı:
malloc () istenen belleğin tek bloğunu atar,
calloc () istenen belleğin birden çok bloğunu atar

Başlatma:
malloc () - ayrılan belleği temizlemez ve başlatmaz.
calloc () - ayrılan belleği sıfıra başlatır.

Hız:
malloc () hızlıdır.
calloc (), malloc () 'dan daha yavaştır.

Bağımsız Değişkenler ve Sözdizimi:
malloc () 1 bağımsız değişken alır:

  1. bayt

    • Ayrılacak bayt sayısı

calloc () 2 bağımsız değişken alır:

  1. uzunluk

    • ayrılacak bellek bloğu sayısı
  2. bayt
    • her bellek bloğuna ayrılacak bayt sayısı
void *malloc(size_t bytes);         
void *calloc(size_t length, size_t bytes);      

Bellek Ayırma Şekli:
malloc işlevi, kullanılabilir yığından istenen 'boyutta' bellek atar.
Calloc işlevi, 'num * boyutuna eşit olan boyutta bir bellek atar.

İsminin Anlamı:
malloc ismi "bellek ayırma" anlamına gelir.
Calloc ismi "bitişik ayırma" anlamına gelir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.