Statik bellek ayırma ve dinamik bellek ayırma arasındaki fark


Yanıtlar:


98

Üç tür tahsis vardır - statik, otomatik ve dinamik.

Statik Tahsis , program başladığında değişkenleriniz için hafızanın tahsis edildiği anlamına gelir. Program oluşturulduğunda boyut sabittir. Global değişkenler, dosya kapsamı değişkenleri ve staticdahili fonksiyonlar ile tanımlanmış değişkenler için geçerlidir .

Otomatik bellek tahsisi , işlevler içinde tanımlanan (statik olmayan) değişkenler için gerçekleşir ve genellikle yığın üzerinde depolanır (C standardı bir yığının kullanılmasını zorunlu kılmasa da). Bunları kullanarak fazladan bellek ayırmanız gerekmez, ancak diğer yandan bu belleğin ömrü üzerinde sınırlı kontrole sahip olursunuz. Örneğin: bir işlevdeki otomatik değişkenler yalnızca işlev bitene kadar oradadır.

void func() {
    int i; /* `i` only exists during `func` */
}

Dinamik bellek tahsisi biraz farklıdır. Artık bu bellek konumlarının tam boyutunu ve kullanım ömrünü kontrol ediyorsunuz. Serbest bırakmazsanız bellek sızıntılarıyla karşılaşırsınız ve bu da uygulamanızın çökmesine neden olabilir, çünkü bir noktada sistem daha fazla bellek ayıramaz.

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

Üstteki örnekte, ayrılan bellek, işlev sonlandırılmış olsa bile hala geçerlidir ve erişilebilirdir. Hafıza ile işiniz bittiğinde, onu boşaltmanız gerekir:

free(mem);

2
Değişkenlerin yaşam süresi üzerinde kontrole sahip olduğunuza emin olun ... kapsamı belirleyen kişi sizsiniz, değil mi?
Luchian Grigore

Tabii ki, ama demek istediğim bu değil. Kapsamını aşmak için değişkenlerin yaşam süresini uzatamazsınız. Ama belki cevabımda bunu açıklığa kavuşturmalıyım. Teşekkürler
Constantinius

5
-1 Bu cevap yanlış. Statik ve otomatik değişkenleri karıştırırsınız .
brice

2
Kendi cümleniz şu şekildedir: " Statik Tahsis, değişkenleriniz için hafızanın otomatik olarak tahsis edildiği anlamına gelir " Bu yanlış . Ne göz at GNU Libc manuel sayfa bu konuda söylenecek vardır.
brice

1
@EliBendersky Şimdi yeniden yazıldı. Şimdi doğru olup olmadığını kontrol edin.
Suraj Jain

121

Bu standart bir mülakat sorusudur:

Dinamik bellek ayırma

Bellek calloc(), malloc()ve arkadaşları kullanılarak çalışma zamanında tahsis edilir . Yığın veri yapısı ref ile ilgisi olmamasına rağmen, bazen 'yığın' bellek olarak da adlandırılır .

int * a = malloc(sizeof(int));

Yığın bellek free()çağrılana kadar kalıcıdır . Başka bir deyişle, değişkenin yaşam süresini siz kontrol edersiniz.

Otomatik bellek ayırma

Bu, genel olarak 'yığın' bellek olarak bilinen şeydir ve yeni bir kapsam girdiğinizde (genellikle çağrı yığınında yeni bir işlev basıldığında) tahsis edilir. Kapsam dışına çıktığınızda, otomatik bellek adreslerinin değerleri tanımsızdır ve bunlara erişmek bir hatadır .

int a = 43;

Kapsamın işlev anlamına gelmediğini unutmayın. Kapsamlar bir işlev içinde yuvalanabilir ve değişken, yalnızca bildirildiği blok içinde kapsam dahilinde olacaktır. Ayrıca bu belleğin nereye tahsis edileceğinin belirtilmediğine dikkat edin. ( Aklı başında bir sistemde yığın veya optimizasyon için kayıtlar olacaktır)

Statik bellek ayırma

Derleme zamanında * tahsis edilir ve statik bellekteki bir değişkenin ömrü, programın yaşam süresidir .

C'de, statik bellek staticanahtar sözcük kullanılarak tahsis edilebilir . Kapsam, yalnızca derleme birimidir.

Şeyler daha ilginç olsun zaman externanahtar kelime olarak kabul edilir . Bir externdeğişken tanımlandığında , derleyici onun için bellek ayırır. Bir externdeğişken bildirildiğinde , derleyici değişkenin başka bir yerde tanımlanmasını gerektirir . externDeğişkenlerin bildirilmemesi / tanımlanamaması bağlantı sorunlarına neden olurken, staticdeğişkenlerin bildirilmemesi / tanımlanamaması derleme sorunlarına neden olur.

dosya kapsamında statik anahtar kelime isteğe bağlıdır (bir işlevin dışında):

int a = 32;

Ancak işlev kapsamında değil (bir işlevin içinde):

static int a = 32;

Teknik olarak externve staticC'deki iki ayrı değişken sınıfıdır.

extern int a; /* Declaration */
int a; /* Definition */

* Statik bellek tahsisi hakkında notlar

Statik belleğin derleme zamanında ayrıldığını söylemek biraz kafa karıştırıcı, özellikle de derleme makinesi ile ana makinenin aynı olmayabileceğini veya hatta aynı mimaride olmayabileceğini düşünmeye başlarsak.

Düşünmek iyi olabilir statik bellek tahsisi derleyici tarafından ele alındığının ziyade derleme zamanında tahsis .

Örneğin derleyici data, derlenmiş ikili dosyada büyük bir bölüm oluşturabilir ve program belleğe yüklendiğinde,dataprogramın bölümü, ayrılan belleğin konumu olarak kullanılacaktır. Bu, çok fazla statik bellek kullanılıyorsa, derlenmiş ikiliyi çok büyük yapmak gibi belirgin bir dezavantaja sahiptir. Yarım düzineden daha az kod satırından oluşturulan çok gigabaytlık bir ikili dosya yazmak mümkündür. Diğer bir seçenek, derleyicinin program çalıştırılmadan önce belleği başka bir şekilde tahsis edecek başlatma kodunu enjekte etmesidir. Bu kod, hedef platforma ve işletim sistemine göre değişecektir. Pratikte, modern derleyiciler bu seçeneklerden hangisinin kullanılacağına karar vermek için buluşsal yöntemler kullanır. Bunu, 10k, 1m, 10m, 100m, 1G veya 10G öğelerinin büyük bir statik dizisini ayıran küçük bir C programı yazarak deneyebilirsiniz. Birçok derleyici için ikili boyut, dizinin boyutuyla doğrusal olarak büyümeye devam edecek ve belirli bir noktayı geçecektir.

Belleği Kaydet

Son bellek sınıfı, 'kayıt' değişkenleridir. Beklendiği gibi, kayıt değişkenleri bir CPU'nun kaydına tahsis edilmelidir, ancak karar aslında derleyiciye bırakılmıştır. Bir yazmaç değişkenini bir referansa adresi-of kullanarak dönüştüremezsiniz.

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

Çoğu modern derleyici, hangi değişkenlerin yazmaçlara konulacağını seçmede sizden daha akıllıdır :)

Referanslar:


3
Not: Bunun int * a = malloc(sizeof(*a));yerine, türünü tekrar etmekten kaçınmanızı öneririm a. Bu, herhangi bir adeğişiklik olursa, işleri çok daha kolaylaştırır .
Shahbaz

1
Aslında buna yığın denir, ancak yığın veri yapısıyla ilgisi yoktur. Bu durumda yığın, dağınık bir yer anlamına gelir
dinamik

2
"Statik bellek tahsisi ... Derleme zamanında tahsis edilir" Tahsisat büyüklüğünün derleme zamanında belirlendiğini mi söylüyorsunuz ? Bir kenara bellek ayarı yalnızca çalışma zamanında olmaz mı?
lf215

Hey, bir şüphem var, eğer hala yanıt veriyorsan :(. Otomatik bellek tahsisi ne olacak? Derleyici ayrıca adresleri bu yerel değişkenler için veri bölümünde saklayacak ve çalıştırılabilir dosyaya aktaracak mı? Ve kod çalıştırıldığında (ve kapsama girdiğinde) ) bu adresler aslında ayrılmış belleğin konumları olarak kullanılacak veya gerçekten derleyicim tarafından herhangi bir adres oluşturma ve işleme olmadan yalnızca çalışma zamanında mı tahsis ediliyor?
LocalHost

1
@LocalHost Otomatik değişkenler, tanımlandıkları bağlamın (kaşlı ayraçlar) yaşam süresine göre ayarlanır. bu genellikle çalışma zamanında çağrı yığınında tahsis edilir. Kesinlikle oluyor değil veri bölümünde saklanır. C18 standardını buradan okuyabilirsiniz: (6.2.4.5-7) web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/…
brice

3

Statik Bellek Tahsisi:

  • Değişkenler kalıcı olarak tahsis edilir
  • Tahsis, program yürütülmeden önce yapılır
  • Statik ayırma uygulamak için yığın adı verilen veri yapısını kullanır
  • Daha az verimli
  • Orada hiçbir bellek yeniden kullanılabilirliği

Dinamik Bellek Tahsisi:

  • Değişkenler yalnızca program birimi aktif hale gelirse tahsis edilir
  • Tahsis, programın yürütülmesi sırasında yapılır
  • Dinamik ayırmayı uygulamak için yığın adı verilen veri yapısını kullanır
  • Daha verimli
  • Orada bellek yeniden kullanılabilirliği . Bellek gerekmediğinde serbest bırakılabilir

1
"Statik Bellek Tahsisi [...] Statik ayırmayı gerçekleştirmek için yığın adı verilen veri yapısını kullanır" Hayır , bu yanlış ve yanıltıcıdır. otomatik ve statik ayırma arasındaki fark için lütfen yazıma bakın. Statik bellek olabilir yığın kullanın. Bu, büyük ölçüde uygulamaya bağlıdır ve aynı uygulama için birden fazla strateji kullanılabilir. "Daha az verimli" ile ne demek istediğinden de emin değilim. @Trieu Toan, bu cevabın anlamını kötü bir düzenleme ile değiştirdin.
brice

2

Statik bellek tahsisi: Derleyici, bildirilen bir değişken için gerekli bellek alanını ayırır.İşlecin adresini kullanarak, ayrılmış adres elde edilir ve bu adres bir işaretçi değişkenine atanabilir.Bildirilen değişkenlerin çoğu statik belleğe sahip olduğundan, bu bir işaretçi değişkenine işaretçi değeri atamanın yolu, statik bellek ayırma olarak bilinir. bellek derleme sırasında atanır.

Dinamik bellek ayırma: Belleği dinamik olarak almak için malloc () veya calloc () gibi işlevleri kullanır.Bu işlevler belleği dinamik olarak almak için kullanılıyorsa ve bu işlevler tarafından döndürülen değerler işaretçi değişkenlerine atanmışsa, bu tür atamalar dinamik bellek olarak bilinir. Tahsis. bellek, çalışma süresi boyunca atanır.


1

STATİK BELLEK TAHSİSİ ve DİNAMİK BELLEK TAHSİSİ Arasındaki Fark

Bellek, programın yürütülmesi başlamadan önce tahsis edilir (Derleme Sırasında).
Bellek, programın yürütülmesi sırasında tahsis edilir.

Yürütme sırasında bellek ayırma veya ayırma eylemi gerçekleştirilmez.
Bellek Bağlamaları, Yürütme sırasında oluşturulur ve yok edilir.

Değişkenler kalıcı olarak tahsis edilmiş olarak kalır.
Yalnızca program birimi etkinken atanır.

Yığınlar ve yığınlar kullanılarak uygulanır.
Veri segmentleri kullanılarak uygulandı.

Değişkenlere erişmek için işaretçi gereklidir.
Dinamik olarak ayrılmış işaretleyicilere gerek yok.

Dinamik'ten daha hızlı yürütme.
Statikten daha yavaş yürütme.

Daha fazla bellek alanı gerekli.
Daha az Bellek alanı gerekli.


1
Dinamik bellek tahsisi Yığın üzerinde tahsis edilirken statik bellek tahsisi Yığın üzerinde tahsis edilir
Usman Kurd

@UsmanKurd Bu genellikle statik bellek ile ilgili olarak yanlıştır. Cevabımı gör.
brice

0

Statik bellek tahsisi, derleme sırasında pf programının yürütülmesinden önce bellek olarak ayrılır. Dinamik bellek tahsisi, programın çalışma zamanında yürütülmesi sırasında ayrılmış bellektir.


-1

Statik bellek ayırma. Ayrılan bellek yığın halinde olacaktır.

int a[10];

Dinamik bellek tahsisi. Ayrılan bellek yığın halinde olacaktır.

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

ve C de Çöp Toplayıcı (GC) olmadığı için ikincisi serbest olmalıdır .

free(a);
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.