“Derleme zamanında ayrılan bellek” gerçekten ne anlama geliyor?


159

C ve C ++ gibi programlama dillerinde, insanlar genellikle statik ve dinamik bellek tahsisine başvururlar. Kavramı anlıyorum ama "Tüm bellek derleme zamanında ayrıldı (ayrılmış)" ifadesi her zaman beni şaşırtıyor.

Derleme, anladığım kadarıyla, yüksek düzey C / C ++ kodunu makine diline dönüştürür ve yürütülebilir bir dosya çıkarır. Derlenmiş bir dosyada bellek nasıl "ayrılır"? Bellek her zaman tüm sanal bellek yönetim öğeleriyle birlikte RAM'de ayrılmıyor mu?

Tanıma göre bellek ayırma bir çalışma zamanı kavramı değil mi?

C / C ++ kodumda 1KB statik olarak ayrılmış bir değişken yaparsam, yürütülebilir dosyanın boyutunu aynı miktarda artıracak mı?

Bu, ifadenin "Statik ayırma" başlığı altında kullanıldığı sayfalardan biridir.

Temel Bilgiler: Bellek ayırma, geçmişte bir gezinti


kod ve veriler çoğu modern mimaride tamamen ayrılmıştır. kaynak dosyalar her iki kod verisini aynı yerde içerirken, bölmenin yalnızca verilere referansları vardır. Bu, kaynaktaki statik verilerin yalnızca referans olarak çözüldüğü anlamına gelir.
Cholthi Paul Ttiopic

Yanıtlar:


184

Derleme zamanında ayrılan bellek, derleyicinin derleme zamanında çözüldüğü ve işlem belleğinin içinde belirli şeylerin tahsis edileceği anlamına gelir.

Örneğin, global bir dizi düşünün:

int array[100];

Derleyici derleme zamanında dizinin boyutunu ve bir büyüklüğünü intbilir, bu nedenle derleme zamanında dizinin tüm boyutunu bilir. Ayrıca, genel bir değişkenin varsayılan olarak statik depolama süresi vardır: işlem belleği alanının statik bellek alanına (.data / .bss bölümü) ayrılır. Bu bilgi göz önüne alındığında , derleyici derleme sırasında dizinin o statik bellek alanının hangi adresinde olacağına karar verir .

Tabii ki bu bellek adresleri sanal adreslerdir. Program kendi tüm bellek alanına sahip olduğunu varsayar (örneğin 0x00000000'den 0xFFFFFFFF'ye). Bu nedenle derleyici "Tamam, dizi 0x00A33211 adresinde" gibi varsayımlar yapabilir. Çalışma zamanında bu adresler MMU ve OS tarafından gerçek / donanım adreslerine çevrilir.

Değer başlatılan statik depolama işleri biraz farklıdır. Örneğin:

int array[] = { 1 , 2 , 3 , 4 };

İlk örneğimizde, derleyici sadece dizinin nereye ayrılacağına karar vererek, bu bilgiyi yürütülebilir dosyaya kaydeder.
Değerle başlatılan şeyler durumunda, derleyici dizinin başlangıç ​​değerini de yürütülebilir dosyaya enjekte eder ve program yükleyicisine program başlangıcında dizi ayırmadan sonra dizinin bu değerlerle doldurulması gerektiğini bildiren kod ekler.

Derleyici tarafından oluşturulan montajın iki örneği (x86 hedefi ile GCC4.8.1):

C ++ kodu:

int a[4];
int b[] = { 1 , 2 , 3 , 4 };

int main()
{}

Çıkış düzeneği:

a:
    .zero   16
b:
    .long   1
    .long   2
    .long   3
    .long   4
main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $0, %eax
    popq    %rbp
    ret

Gördüğünüz gibi, değerler doğrudan montaja enjekte edilir. Dizide a, derleyici 16 baytlık sıfır başlatma oluşturur, çünkü Standart statik olarak saklanan şeylerin varsayılan olarak sıfıra başlatılması gerektiğini söyler:

8.5.9 (Başlatıcılar) [Not]:
Statik depolama süresindeki her nesne, başka bir başlatma yapılmadan önce program başlangıcında sıfırdan başlatılır. Bazı durumlarda, ek başlatma daha sonra yapılır.

Her zaman insanların derleyicinin gerçekten C ++ kodu ile ne yaptığını görmek için kodlarını sökme öneririz. Bu, depolama sınıflarından / süresinden (bu soru gibi) gelişmiş derleyici optimizasyonlarına uygulanır. Derleyicinize montajı oluşturma talimatı verebilirsiniz, ancak bunu internette dostça bir şekilde yapmak için harika araçlar vardır. Benim favorim GCC Explorer .


2
Teşekkürler. Bu çok açıklığa kavuşur. Böylece derleyici "değişken dizisi [] vb. İçin 0xABC'den 0xXYZ'ye bellek ayır" ifadesine eşdeğer bir çıktı üretir. ve sonra yükleyici programı çalıştırmadan hemen önce tahsis etmek için bunu kullanıyor?
Talha Sayed

1
@TalhaSayed tam olarak.
Örneğe

2
@Secko Ben işleri basitleştirdim. Bu program hakkında sadece bir söz sanal bellek üzerinden çalışır, ama soru sanal bellek hakkında değil gibi ben konuyu genişletmemiştir. Sadece sanal bellek sayesinde derleyicinin derleme zamanında bellek adresleri hakkında varsayımlar yapabileceğini gösteriyordum.
Manu343726

2
@Secko evet. mmm "oluşturulan" daha iyi bir terim olduğunu düşünüyorum.
Manu343726

2
"Bu işlem bellek alanı statik mamory alanı tahsis " Benim işlem bellek alanı bazı statik meme alanları tahsis Okuma.
Radiodef

27

Derleme zamanında ayrılan bellek, çalışma zamanında başka bir ayırmanın olmayacağı anlamına gelir - malloc, yeni veya diğer dinamik ayırma yöntemlerine çağrı yapılmaz. Her zaman bu belleğe ihtiyaç duymasanız bile sabit miktarda bellek kullanacaksınız.

Tanıma göre bellek ayırma bir çalışma zamanı kavramı değil mi?

Bellek, çalışma süresinden önce kullanılmaz , ancak yürütmeye başlamadan hemen önce tahsisi sistem tarafından işlenir.

C / C ++ kodumda 1KB statik olarak ayrılmış bir değişken yaparsam, yürütülebilir dosyanın boyutunu aynı miktarda artıracak mı?

Statik olarak bildirmek, yürütülebilir dosyanızın boyutunu birkaç bayttan daha fazla artırmaz. Sıfır olmayan bir başlangıç ​​değeri ile bildirilmesi (bu başlangıç ​​değerini tutmak için). Bunun yerine, bağlayıcı bu 1KB tutarını, sistemin yükleyicisinin yürütmeden hemen önce sizin için oluşturduğu bellek gereksinimine ekler.


1
i yazarsanız static int i[4] = {2 , 3 , 5 ,5 }çalıştırılabilir boyuta göre 16 bayt artar. "Statik olarak bildirmek çalıştırılabilirinizin boyutunu birkaç bayttan daha fazla artırmayacaktır. Sıfır olmayan bir başlangıç ​​değeri ile bildirmek" İlk değeri ile bildirmek ne anlama gelecektir.
Suraj Jain

Yürütülebilir dosyanızın statik veri için iki alanı vardır - biri başlatılmamış statik ve diğeri başlatılmış statik için. Başlatılmamış alan gerçekten sadece bir boyut göstergesidir; programınız çalıştırıldığında, bu boyut statik depolama alanını büyütmek için kullanılır, ancak programın kendisinin başlatılmamış verilerin kullanılmasından daha fazla bir şey tutması gerekmiyordu. Başlatılan statik için, programınızın yalnızca statik (her biri) boyutunu değil, aynı zamanda başlatıldığı şeyi de tutması gerekir. Böylece örneğinizde, programınızda 2, 3, 5 ve 5 olacaktır.
mah

Nereye yerleştirildiği / nasıl tahsis edileceği konusunda tanımlanan bir uygulamadır, ancak bilmem gerektiğini anladığımdan emin değilim.
mah

23

Derleme zamanında ayrılan bellek, programı yüklediğinizde, belleğin bir kısmının derhal tahsis edileceği ve bu tahsisin boyutu ve (göreceli) konumunun derleme zamanında belirlendiği anlamına gelir.

char a[32];
char b;
char c;

Bu 3 değişken "derleme zamanında tahsis edilir", yani derleyicinin derleme zamanında boyutlarını (sabit olan) hesapladığı anlamına gelir. Değişken a, bellekte bir ofset olacaktır, diyelim ki 0 badresini gösterir, adres 33 ve c34'ü işaret eder (hizalama optimizasyonu olmadığını varsayar). Bu nedenle, 1Kb statik veri ayırmak, kodunuzun boyutunu artırmayacaktır , çünkü sadece içindeki bir ofseti değiştirecektir. Gerçek alan yükleme sırasında tahsis edilecektir .

Gerçek bellek ayırma her zaman çalışma zamanında gerçekleşir, çünkü çekirdeğin onu takip etmesi ve dahili veri yapılarını güncellemesi gerekir (her işlem, sayfa vb. İçin ne kadar bellek ayrılır). Fark, derleyicinin kullanacağınız her verinin boyutunu zaten bilmesidir ve bu, programınız yürütülür yürütülmez tahsis edilir.

Ayrıca göreli adresler hakkında konuştuğumuzu da unutmayın . Değişkenin bulunacağı gerçek adres farklı olacaktır. Yükleme sırasında çekirdek işlem için bir miktar bellek ayıracak, diyelim ki adreste xve çalıştırılabilir dosyada bulunan tüm sabit kodlanmış adresler xbayt tarafından artırılacak , böylece aörnekteki değişken adres x, b adresinde x+33ve yakında.


17

Yığına N bayt alan değişkenler eklemek (zorunlu olarak) kutunun boyutunu N bayt artırmaz. Aslında, çoğu zaman birkaç bayt ekleyecektir.
Senin koduna 1000 karakter ekleyerek nasıl bir örnek ile başlayalım olacak lineer bir şekilde bin'in boyutunu artırmak.

1k, bin karakterden oluşan bir dize ise, bu şekilde bildirilir

const char *c_string = "Here goes a thousand chars...999";//implicit \0 at end

ve o zaman, vim your_compiled_bino dizeyi bir yerlerde depoda görebiliyordunuz. Bu durumda, evet: çalıştırılabilir metin tam olarak içerdiğinden 1 k daha büyük olacaktır.
Bununla birlikte , yığına bir ints, chars veya longs dizisi atar ve bunu bir döngüde atarsanız , bu satırlar boyunca bir şey

int big_arr[1000];
for (int i=0;i<1000;++i) big_arr[i] = some_computation_func(i);

o zaman hayır: 1000*sizeof(int)
kutuyu arttırmayacaktır ... derleme zamanında Tahsis ile şu an anlama geldiğiniz anlamına gelir (yorumlarınıza dayanarak): derlenmiş depo sistemde ne kadar bellek gerektiğini bilmek için gerekli bilgileri içerir uygulamanızın istediği yığın boyutu hakkındaki bilgilerin yanı sıra yürütüldüğünde hangi işlev / bloğa ihtiyaç duyacağı. Sistem, bölmenizi yürüttüğünde ayıracağı şey budur ve programınız bir işlem haline gelir (yani, bölgenizin yürütülmesi ... söylediklerimi alırsınız).
Tabii ki, tam resmi burada boyamıyorum: Çöp kutusu, çöp kutusunun gerçekten ne kadar büyük bir desteğe ihtiyacı olacağı hakkında bilgi içerir. Bu bilgilere dayanarak (diğer şeylerin yanı sıra), sistem, yığın adı verilen ve programın bir tür serbest saltanat elde edeceği bir yığın bellek ayıracaktır. İşlem (bölmenin yürütüldüğünün sonucu) başlatıldığında yığın belleği yine de sistem tarafından ayrılır. İşlem daha sonra yığın belleğini sizin için yönetir. Bir işlev veya döngü (herhangi bir blok türü) çağrıldığında / yürütüldüğünde, o bloğa yerel değişkenler yığına itilir ve başkaları tarafından kullanılmak üzere kaldırılır (yığın belleği " konuşulacak şekilde " serbest bırakılır ) işlevleri / blokları. Yani beyan etmekint some_array[100]kutuya yalnızca birkaç bayt ek bilgi ekler, bu da sisteme X işlevinin 100*sizeof(int)+ bir miktar kitap tutma alanı gerektireceğini söyler .


Çok teşekkürler. Bir soru daha, fonksiyonlar için yerel değişkenler de derleme zamanında aynı şekilde tahsis ediliyor mu?
Talha Sayed

@TalhaSayed: Evet, dediğimde bunu kastettim: "Sistemin hangi fonksiyon / bloğun ne kadar bellek gerektireceğini bilmesi gereken bilgiler." Bir işlevi çağırdığınızda, sistem o işlev için gerekli belleği tahsis edecektir. İşlev döndüğü anda o bellek tekrar serbest bırakılır.
Elias Van Ootegem

C kodunuzdaki yorumlara gelince: Aslında / zorunlu olarak olan bu değil. Örneğin, dize büyük olasılıkla derleme zamanında yalnızca bir kez tahsis edilecektir. Böylece asla "serbest" (ayrıca ben terminoloji genellikle sadece bir şey dinamik olarak ayırdığınızda kullanılır düşünüyorum), i"serbest" ya da ya değil. Eğer ibellekte kalacak olsaydı, sadece yığına itilirdi, kelimenin anlamında özgür olmayan, bunu göz ardı eden iya cda tüm zaman boyunca kayıtlarda tutulacak bir şey. Tabii ki, bunların hepsi derleyiciye bağlı, yani siyah ve beyaz değil.
phant0m

@ phant0m: Asla dizenin yığına tahsis edildiğini söylemedim , sadece işaretçi de olurdu, dizenin kendisi salt okunur bellekte kalacaktı. Yerel değişkenlerle ilişkili belleğin free()aramalar anlamında serbest kalmadığını biliyorum , ancak kullandıkları yığın bellek, listelediğim işlev döndükten sonra diğer işlevler tarafından kullanım için ücretsiz. Bazıları için kafa karıştırıcı olabilir çünkü kodu kaldırdım
Elias Van Ootegem

Ah, anlıyorum. Bu durumda benim yorumumu alın, "İfadenizle kafam karıştı".
phant0m

16

Birçok platformda, her modül içerisindeki tüm global veya statik ayırmalar, derleyici tarafından üç veya daha az konsolide ayırmaya (biri başlatılmamış veriler için (genellikle "bss" olarak adlandırılır), biri de başlatılabilir yazılabilir veriler için (genellikle "veri" olarak adlandırılır) birleştirilir. ) ve biri sabit veri ("const")) ve bir programdaki her türün tüm global veya statik ayırmaları, bağlayıcı tarafından her tür için bir global olarak birleştirilecektir. Örneğin int, dört bayt olduğu varsayılarak , bir modülün yalnızca statik ayırmaları olarak aşağıdakileri vardır:

int a;
const int b[6] = {1,2,3,4,5,6};
char c[200];
const int d = 23;
int e[4] = {1,2,3,4};
int f;

bağlayıcıya bss için 208 bayt, "veri" için 16 bayt ve "const" için 28 bayt gerektiğini söyler. Ayrıca, bir değişkene yapılan herhangi bir referans bir alan seçici ve ofset ile değiştirilir, böylece a, b, c, d ve e bss + 0, const + 0, bss + 4, const + 24, veri ile değiştirilir Sırasıyla +0 veya bss + 204.

Bir program bağlandığında, tüm modüllerin tüm bss alanları birbirine birleştirilir; aynı şekilde veri ve sabit alanlar. Her modül için, herhangi bir bss-göreceli değişkenin adresi, önceki tüm modüllerin bss alanlarının boyutuna göre artırılacaktır (yine aynı şekilde veri ve sabit ile). Dolayısıyla, bağlayıcı yapıldığında, herhangi bir program bir bss tahsisi, bir veri tahsisi ve bir sabit tahsisine sahip olacaktır.

Bir program yüklendiğinde, platforma bağlı olarak genellikle dört şeyden biri gerçekleşir:

  1. Yürütülebilir dosya, her bir veri türü için ve - ilk içeriğin bulunabileceği başlangıç ​​veri alanı için kaç bayt gerektiğini belirtir. Ayrıca bss, veri veya sabit adres kullanan tüm talimatların bir listesini de içerecektir. İşletim sistemi veya yükleyici, her bir alan için uygun miktarda alan ayıracak ve daha sonra o alanın başlangıç ​​adresini, ihtiyaç duyan her talimata ekleyecektir.

  2. İşletim sistemi, üç tür verinin tümünü tutmak için bir bellek parçası tahsis eder ve uygulamaya bu bellek yığınına bir işaretçi verir. Statik veya global veri kullanan herhangi bir kod, söz konusu işaretçiye göre bu kodu kullanmaz (çoğu durumda işaretçi, bir uygulamanın ömrü boyunca bir kayıt defterinde saklanır).

  3. İşletim sistemi başlangıçta ikili kodunu saklayanlar dışında uygulamaya herhangi bir bellek ayırmayacaktır, ancak uygulamanın yaptığı ilk şey, işletim sisteminden uygun bir ayırma istemek olacaktır.

  4. İşletim sistemi başlangıçta uygulama için yer ayırmayacak, ancak uygulama başlangıçta (yukarıdaki gibi) uygun bir ayırma isteyecektir. Uygulama, belleğin nereye tahsis edildiğini (ilk stilde olduğu gibi) yansıtacak şekilde güncellenmesi gereken adreslerin bulunduğu bir talimatlar listesi içerecektir, ancak uygulamanın işletim sistemi yükleyicisi tarafından yamasını sağlamak yerine, uygulama kendisini yamalamak için yeterli kod içerecektir .

Dört yaklaşımın da avantajları ve dezavantajları vardır. Bununla birlikte, her durumda, derleyici rasgele sayıda statik değişkeni sabit az sayıda bellek isteğinde birleştirecek ve bağlayıcı tüm bunları az sayıda konsolide ayırmada birleştirecektir. Bir uygulamanın işletim sisteminden veya yükleyiciden bir yığın bellek alması gerekecek olsa da, o büyük yığından ayrı ayrı parçaları ihtiyaç duyan tüm değişkenlere tahsis etmekten sorumlu olan derleyici ve bağlayıcıdır.


13

Sorunuzun özü şudur: "Bellek" derlenmiş bir dosyada nasıl ayrılır? "Bellek her zaman tüm sanal bellek yönetimi öğeleriyle RAM'de ayrılmaz mı? Tanım gereği bellek ayırma bir çalışma zamanı kavramı değil mi?"

Bence sorun, bellek tahsisinde iki farklı kavramın bulunması. Temel olarak, bellek ayırma işlemi, "bu veri öğesi bu özel bellek yığınında saklanır" dediğimiz süreçtir. Modern bir bilgisayar sisteminde, bu iki aşamalı bir süreci içerir:

  • Bazı sistem, öğenin saklanacağı sanal adrese karar vermek için kullanılır
  • Sanal adres fiziksel bir adresle eşlenir

İkinci işlem tamamen çalışma süresidir, ancak veri bilinen bir boyuta sahipse ve sabit bir sayı gerekiyorsa, önceki derleme zamanında yapılabilir. Temel olarak şu şekilde çalışır:

  • Derleyici, şuna benzer bir satır içeren bir kaynak dosyası görür:

    int c;
  • Montajcı için 'c' değişkeni için bellek ayırmasını söyleyen çıktı üretir. Bu şöyle görünebilir:

    global _c
    section .bss
    _c: resb 4
  • Montajcı çalıştığında, bellek 'segmenti' (veya 'bölümü') başlangıcından itibaren her öğenin ofsetlerini izleyen bir sayaç tutar. Bu, dosyadaki her şeyi içeren çok büyük bir 'yapının' parçaları gibidir, şu anda kendisine tahsis edilmiş gerçek bir belleğe sahip değildir ve herhangi bir yerde olabilir. _cBelirli bir ofsete sahip bir tabloya dikkat çeker (örneğin, segmentin başlangıcından itibaren 510 bayt) ve ardından sayacını 4 arttırır, böylece bir sonraki değişken (örneğin) 514 baytta olacaktır. Adresine ihtiyaç duyan herhangi bir kod için _c, çıktı dosyasına sadece 510 koyar ve çıktının _cdaha sonra eklenmesini içeren segmentin adresine ihtiyacı olduğunu not eder .

  • Bağlayıcı, birleştiricinin tüm çıktı dosyalarını alır ve inceler. Her segment için bir adres belirler, böylece üst üste binmezler ve talimatların yine de doğru veri öğelerine başvurması için gerekli ofsetleri eklerler. Tarafından işgal edilen gibi başlatılmamış bellek durumundac(toplayıcıya, belleğin derleyicinin başlatılmamış bellek için ayrılmış bir ad olan '.bss' segmentine koymasıyla başlatılamayacağı söylendi), çıktısında işletim sistemine söyleyen bir başlık alanı içeriyor ne kadar rezerve edilmesi gerekiyor. Yeniden yerleştirilebilir (ve genellikle öyledir), ancak genellikle belirli bir bellek adresine daha verimli yüklenmek üzere tasarlanmıştır ve işletim sistemi bu adrese yüklemeyi dener. Bu noktada, sanal adresin ne tarafından kullanılacağı konusunda oldukça iyi bir fikrimiz var c.

  • Fiziksel adres aslında program çalışana kadar belirlenmez. Bununla birlikte, programcının bakış açısından fiziksel adres aslında ilgisizdir - ne olduğunu bile bulamayacağız, çünkü işletim sistemi genellikle kimseyi söylemekten rahatsız olmaz, sık sık değişebilir (program çalışırken) ve İşletim Sisteminin temel amacı bunu yine de soyutlamaktır.


9

Bir yürütülebilir dosya, statik değişkenler için ayrılacak alanı açıklar. Bu ayırma, yürütülebilir dosyayı çalıştırdığınızda sistem tarafından yapılır. Yani 1kB statik değişkeniniz 1kB ile çalıştırılabilir dosyanın boyutunu artırmaz:

static char[1024];

Elbette bir başlatıcı belirtmedikçe:

static char[1024] = { 1, 2, 3, 4, ... };

Bu nedenle, 'makine dili'ne (yani CPU talimatları) ek olarak, bir yürütülebilir dosya gerekli bellek düzeninin açıklamasını içerir.


5

Bellek birçok şekilde tahsis edilebilir:

  • uygulama yığınında (program başlatıldığında tüm yığın OS tarafından uygulamanız için ayrılır)
  • işletim sistemi yığınında (böylece daha fazla yakalayabilirsiniz)
  • çöp toplayıcı kontrollü yığın içinde (her ikisiyle aynı)
  • Yığın üzerinde (böylece yığın taşması elde edebilirsiniz)
  • ikili kodunuzun kod / veri bölümünde ayrılmıştır (yürütülebilir)
  • uzak bir yerde (dosya, ağ - ve bu belleğe bir işaretçi olmayan bir tanıtıcı alırsınız)

Şimdi sorunuz "derleme zamanında ayrılan bellek" nedir. Kesinlikle yanlış bir şekilde ifade edilen bir deyimdir, ki bu ikili segment tahsisine veya yığın tahsisine ya da bazı durumlarda bir yığın tahsisine atıfta bulunur, ancak bu durumda tahsis görünmez kurucu çağrısı ile programcı gözlerinden gizlenir. Ya da muhtemelen, sadece belleğin yığın üzerinde tahsis edilmediğini söylemekle kalmayıp yığın veya segment tahsislerini bilmediğini söyleyen kişi (Ya da bu tür ayrıntılara girmek istemedi).

Ancak çoğu durumda kişi sadece ayrılan bellek miktarının derleme zamanında bilindiğini söylemek ister .

İkili boyut, yalnızca bellek uygulamanızın kodunda veya veri segmentinde ayrıldığında değişir.


1
Bu yanıt, "uygulama yığını", "OS yığını" ve "GC yığını" hakkında, bunların hepsi anlamlı kavramlarmış gibi konuşması nedeniyle kafa karıştırıcı (veya karışık). # 1 ile bazı programlama dillerinin (varsayımsal olarak) .data bölümünde sabit boyutlu bir arabellekten bellek ayıran bir "yığın ayırma" düzeni kullanabileceğini söylemeye çalışıyorsunuz, ancak bu zararlı olabilecek kadar gerçekçi görünmüyor OP'nin anlayışına. Re # 2 ve # 3, bir GC'nin varlığı gerçekten hiçbir şeyi değiştirmez. Ve yeniden 5, .datave arasındaki nispeten çok daha önemli ayrımı atladınız .bss.
Quuxplusone

4

Haklısın. Bellek aslında yükleme sırasında, yani yürütülebilir dosya (sanal) belleğe getirildiğinde tahsis edilir (sayfalandırılır). Bellek o anda başlatılabilir. Derleyici sadece bir bellek haritası oluşturur. [Bu arada, yığın ve yığın boşlukları da yükleme zamanında tahsis edilir!]


2

Sanırım biraz geri adım atman gerek. Derleme zamanında ayrılan bellek .... Bu ne anlama geliyor? Henüz tasarlanmamış olan yongalar üzerindeki belleğin, henüz tasarlanmamış bilgisayarlar için bir şekilde rezerve edildiği anlamına gelebilir mi? Hayır. Hayır, zaman yolculuğu, evreni manipüle edebilecek derleyiciler yok.

Yani, derleyicinin bu belleği bir şekilde çalışma zamanında tahsis etmek için talimatlar ürettiği anlamına gelmelidir. Ancak ona doğru açıdan bakarsanız, derleyici tüm talimatları üretir, bu yüzden fark ne olabilir. Fark, derleyicinin karar vermesidir ve çalışma zamanında kodunuz kararlarını değiştiremez veya değiştiremez. Derleme zamanında 50 bayta ihtiyaç duyduğuna karar verdiyse, 60'ı ayırmaya karar veremezsiniz - bu karar zaten verilmişti.


Sokratik yöntemi kullanan cevapları seviyorum, ama yine de "derleyicinin bu hafızayı bir şekilde ayırmak için talimatlar oluşturduğu" hatalı sonucuna varmıştım. Bir derleyicinin herhangi bir çalışma zamanı "talimatı" oluşturmadan nasıl "bellek ayırabildiğini" görmek için en çok oy alan cevaba göz atın. (Bir montaj dili bağlamındaki "talimatlar" ın belirli bir anlamı, yani çalıştırılabilir opcodlar olduğunu unutmayın. Kelimeyi konuşma dilinde "yemek tarifi" gibi bir şey ifade etmek için kullanıyor olabilirsiniz , ancak bu bağlamda OP'yi karıştırırsınız. )
Quuxplusone

1
@Quuxplusone: Bu cevabı okudum (ve oyladım). Ve hayır, cevabım özel olarak başlatılmış değişkenler konusunu ele almıyor. Kendini değiştiren kodu da ele almaz. Bu cevap mükemmel olsa da, önemli bir konuyu düşündüğüm konulara değinmedi - bir şeyleri bağlama koymak. Dolayısıyla umarım cevabım OP'nin (ve diğerlerinin) durmasına ve neler olup bittiğini düşünmesine yardımcı olur, anlamadıkları sorunlar olduğunda.
jmoreno

@Quuxplusone: Burada yanlış iddialarda bulunursam özür dilerim, ama ben de cevabımı -1'leyenlerden biriydin. Eğer öyleyse, cevabımın hangi kısmının bunu yapmanın ana nedeni olduğunu dikkatlice işaret eder misiniz ve düzenlememi de kontrol etmek ister misiniz? Yığın belleğinin nasıl yönetildiğinin gerçek iç parçaları hakkında birkaç parça atladığımı biliyorum, bu yüzden şimdi zaten cevabım için% 100 doğru
olmamam

@jmoreno "Henüz tasarlanmamış yongalar üzerinde henüz tasarlanmamış yongalar üzerindeki belleğin bir şekilde rezerve edildiği anlamına gelebilir mi? Hayır." "tahsis" kelimesinin beni baştan beri karıştırdığı yanlış anlamdır. Bu cevabı beğendim, çünkü tam olarak işaret etmeye çalıştığım problemi ifade ediyor. Buradaki cevapların hiçbiri bu noktaya gerçekten dokunmadı. Teşekkürler.
Talha Sayed

2

Montaj programlamayı öğrenirseniz, veri, yığın ve kod, vb. İçin segmentler yapmanız gerektiğini göreceksiniz. Veri segmenti, dizelerinizin ve sayılarınızın bulunduğu yerdir. Kod segmenti, kodunuzun yaşadığı yerdir. Bu segmentler yürütülebilir programa yerleştirilmiştir. Tabii ki yığın boyutu da önemlidir ... yığın taşması istemezsiniz !

Veri segmentiniz 500 bayt ise, programınızın 500 bayt alanı vardır. Veri segmentini 1500 bayta değiştirirseniz, programın boyutu 1000 bayt daha büyük olacaktır. Veriler gerçek programa birleştirilir.

Üst düzey dilleri derlediğinizde olan budur. Gerçek veri alanı, yürütülebilir bir programda derlendiğinde, programın boyutunu artırarak ayrılır. Program anında bellek talep edebilir ve bu dinamik bellektir. RAM'den bellek talep edebilirsiniz ve CPU bunu kullanmanıza izin verir, bırakabilirsiniz ve çöp toplayıcınız CPU'ya geri bırakacaktır. Gerekirse, iyi bir bellek yöneticisi tarafından sabit diske de değiştirilebilir. Bu özellikler üst düzey dillerin size sağladığı özelliklerdir.


2

Bu kavramları birkaç diyagram yardımıyla açıklamak istiyorum.

Bu kesin olarak derleme zamanında bellek ayrılamadığı doğrudur. Ancak, derleme zamanında gerçekte ne olur.

İşte açıklama geliyor. Örneğin, bir programın dört değişkeni x, y, z ve k'dir. Şimdi, derleme zamanında, bu değişkenlerin birbirine göre konumunun tespit edildiği bir hafıza haritası yapar. Bu şema daha iyi gösterecektir.

Şimdi hayal edin, bellekte hiçbir program çalışmıyor. Bunu büyük bir boş dikdörtgenle gösteriyorum.

boş alan

Ardından, bu programın ilk örneği yürütülür. Aşağıdaki gibi görselleştirebilirsiniz. Bu aslında belleğin tahsis edildiği zamandır.

ilk örnek

Bu programın ikinci örneği çalışırken, bellek aşağıdaki gibi görünecektir.

ikinci örnek

Ve üçüncüsü ..

üçüncü örnek

Bu böyle devam eder.

Umarım bu görselleştirme bu kavramı iyi açıklar.


2
Bu diyagramlar statik ve dinamik bellek arasındaki farkı gösterirse, IMHO daha faydalı olacaktır.
Bartek Banachewicz

Bu şeyleri basit tutmak için benden kaçınılmıştı. Odaklandığım nokta bu funda fazla teknik karmaşa olmadan açık bir şekilde açıklamak. Bu statik değişken için olduğu sürece .. Bu nokta önceki cevaplar tarafından iyi tespit edilmiştir.Bu yüzden bunu atladım.
user3258051

1
Eh, bu kavram özellikle karmaşık değil, bu yüzden neden olması gerekenden daha basit hale getiremiyorum, ama sadece ücretsiz bir cevap anlamına geldiğinden, tamam.
Bartek Banachewicz

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.