Wat en waar zijn de stapel en heap?

Programmeertaalboeken leggen uit dat waardetypes worden gemaakt op de stapelen referentietypes worden gemaakt op de heap, zonder uit te leggen wat deze twee dingen zijn. Ik heb hier geen duidelijke uitleg over gelezen. Ik begrijp wat een stapelis. Maar,

  • Waar en wat zijn ze (fysiek in het geheugen van een echte computer)?
  • In hoeverre worden ze bestuurd door het besturingssysteem of de runtime van de taal?
  • Wat is hun bereik?
  • Wat bepaalt de grootte van elk van hen?
  • Wat maakt iemand sneller?

Antwoord 1, autoriteit 100%

De stapel is het geheugen dat is gereserveerd als werkruimte voor een uitvoeringsdraad. Wanneer een functie wordt aangeroepen, wordt een blok bovenaan de stapel gereserveerd voor lokale variabelen en enkele boekhoudgegevens. Wanneer die functie terugkeert, wordt het blok ongebruikt en kan het de volgende keer dat een functie wordt aangeroepen worden gebruikt. De stapel wordt altijd gereserveerd in een LIFO-volgorde (last in first out); het meest recent gereserveerde blok is altijd het volgende blok dat moet worden vrijgemaakt. Dit maakt het heel eenvoudig om de stapel bij te houden; het bevrijden van een blok van de stapel is niets meer dan één aanwijzer aanpassen.

De heap is geheugen dat is gereserveerd voor dynamische toewijzing. In tegenstelling tot de stapel, is er geen afgedwongen patroon voor het toewijzen en vrijgeven van blokken van de heap; u kunt op elk moment een blokkering toewijzen en op elk moment vrijgeven. Dit maakt het veel complexer om bij te houden welke delen van de heap op een bepaald moment worden toegewezen of vrijgemaakt; er zijn veel aangepaste heaptoewijzers beschikbaar om de heapprestaties af te stemmen op verschillende gebruikspatronen.

Elke thread krijgt een stapel, terwijl er meestal maar één heap is voor de toepassing (hoewel het niet ongebruikelijk is om meerdere heaps te hebben voor verschillende soorten toewijzing).

Om uw vragen direct te beantwoorden:

In hoeverre worden ze beheerd door het besturingssysteem of de taalruntime?

Het besturingssysteem wijst de stapel toe aan elke thread op systeemniveau wanneer de thread wordt gemaakt. Meestal wordt het besturingssysteem aangeroepen door de taalruntime om de heap voor de toepassing toe te wijzen.

Wat is hun bereik?

De stapel is aan een draad bevestigd, dus wanneer de draad de stapel verlaat, wordt de stapel teruggewonnen. De heap wordt meestal toegewezen bij het opstarten van de applicatie door de runtime en wordt teruggewonnen wanneer de applicatie (technisch proces) wordt afgesloten.

Wat bepaalt de grootte van elk van hen?

De grootte van de stapel wordt ingesteld wanneer een thread wordt gemaakt. De grootte van de heap wordt ingesteld bij het opstarten van de applicatie, maar kan groeien naarmate er ruimte nodig is (de allocator vraagt om meer geheugen van het besturingssysteem).

Wat maakt iemand sneller?

De stapel is sneller omdat het toegangspatroon het triviaal maakt om er geheugen van toe te wijzen en ongedaan te maken (een pointer/integer wordt gewoon verhoogd of verlaagd), terwijl de heap veel complexere boekhouding heeft bij een toewijzing of dealtoewijzing. Ook wordt elke byte in de stapel vaak opnieuw gebruikt, wat betekent dat deze vaak wordt toegewezen aan de cache van de processor, waardoor deze erg snel is. Een andere prestatiehit voor de heap is dat de heap, die meestal een wereldwijde hulpbron is, doorgaans multi-threading-veilig moet zijn, dat wil zeggen dat elke toewijzing en deallocatie – meestal – moet worden gesynchroniseerd met “alle” andere heap-toegangen in het programma.

Een duidelijke demonstratie:


Bron afbeelding: vikashazrati .wordpress.com


Antwoord 2, autoriteit 39%

Stapel:

  • Opgeslagen in computer-RAM, net als de hoop.
  • Variabelen die op de stapel zijn gemaakt, vallen buiten het bereik en worden automatisch ongedaan gemaakt.
  • Veel sneller toe te wijzen in vergelijking met variabelen op de heap.
  • Geïmplementeerd met een daadwerkelijke stapelgegevensstructuur.
  • Slaat lokale gegevens op, retouradressen, gebruikt voor het doorgeven van parameters.
  • Kan een stack overflow hebben wanneer te veel van de stack wordt gebruikt (meestal door oneindige of te diepe recursie, zeer grote toewijzingen).
  • Gegevens die op de stapel zijn gemaakt, kunnen zonder aanwijzers worden gebruikt.
  • U zou de stapel gebruiken als u precies weet hoeveel gegevens u moet toewijzen vóór de compileertijd en deze niet te groot is.
  • Meestal is er al een maximumgrootte bepaald wanneer je programma start.

Hoop:

  • Opgeslagen in computer-RAM, net als de stapel.
  • In C++ moeten variabelen op de heap handmatig worden vernietigd en mogen ze nooit buiten het bereik vallen. De gegevens worden vrijgegeven met delete, delete[]of free.
  • Langzamer om toe te wijzen in vergelijking met variabelen op de stapel.
  • Gebruikt op aanvraag om een gegevensblok toe te wijzen voor gebruik door het programma.
  • Kan fragmentatie hebben als er veel toewijzingen en deallocaties zijn.
  • In C++ of C worden gegevens die op de heap zijn gemaakt, aangeduid met verwijzingen en toegewezen met respectievelijk newof malloc.
  • Kan toewijzingsfouten hebben als een te grote buffer wordt aangevraagd om te worden toegewezen.
  • U zou de hoop gebruiken als u niet precies weet hoeveel gegevens u nodig hebt bij RUN TIME of als u veel gegevens nodig hebt.
  • verantwoordelijk voor geheugenlekken.

Voorbeeld:

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];
    //Create 500 bytes on the heap
    pBuffer = new char[500];
   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;

3, Autoriteit 22%

Het belangrijkste punt is dat heap en stapel generieke voorwaarden zijn voor manieren waarop het geheugen kan worden toegewezen. Ze kunnen op veel verschillende manieren worden geïmplementeerd en de voorwaarden zijn van toepassing op de basisconcepten.

  • In een stapel items zitten items er een op de bovenkant van de andere in de volgorde waarin ze daar zijn geplaatst, en je kunt alleen de bovenste verwijderen (zonder het hele ding te overtreffen).

    De eenvoud van een stapel is dat u geen tabel hoeft te houden met een record van elke sectie van toegewezen geheugen; De enige overheidsinformatie die u nodig hebt, is een enkele aanwijzer naar het einde van de stapel. TOEKENNEN EN DE-TOEKENT, UITVOEREN EN VERTROUNT EN VERKINT DIE ENKELE POINTER. OPMERKING: een stapel kan soms worden geïmplementeerd om bovenaan een gedeelte van het geheugen te starten en naar beneden uit te strekken in plaats van naar boven te groeien.

  • In een heap is er geen specifieke volgorde aan de manier waarop items worden geplaatst. U kunt in elke bestelling in- en verwijderen en verwijderen, omdat er geen duidelijk item ‘TOP’ is.

    Heap-toewijzing vereist het bijhouden van een volledig overzicht van welk geheugen is toegewezen en wat niet, evenals enig overheadonderhoud om fragmentatie te verminderen, aaneengesloten geheugensegmenten te vinden die groot genoeg zijn voor de gevraagde grootte, enzovoort. Geheugen kan op elk moment worden vrijgemaakt, waardoor er vrije ruimte overblijft. Soms voert een geheugentoewijzer onderhoudstaken uit, zoals het defragmenteren van geheugen door toegewezen geheugen te verplaatsen of het verzamelen van afval – tijdens runtime identificeren wanneer geheugen niet langer in het bereik is en de toewijzing ervan ongedaan maken.

Deze afbeeldingen zouden een redelijk goede beschrijving moeten geven van de twee manieren om geheugen toe te wijzen en vrij te maken in een stapel en een heap. Jammie!

  • In hoeverre worden ze beheerd door het besturingssysteem of de taalruntime?

    Zoals gezegd zijn heap en stack algemene termen en kunnen ze op veel manieren worden geïmplementeerd. Computerprogramma’s hebben meestal een stapel genaamd een call-stackdie informatie opslaat die relevant is voor de huidige functie, zoals een pointer naar de functie waaruit deze is aangeroepen, en eventuele lokale variabelen. Omdat functies andere functies aanroepen en vervolgens terugkeren, groeit en krimpt de stapel om informatie te bevatten van de functies verderop in de aanroepstack. Een programma heeft er niet echt runtime-controle over; het wordt bepaald door de programmeertaal, het besturingssysteem en zelfs de systeemarchitectuur.

    Een heap is een algemene term die wordt gebruikt voor elk geheugen dat dynamisch en willekeurig wordt toegewezen; d.w.z. niet in orde. Het geheugen wordt meestal toegewezen door het besturingssysteem, waarbij de toepassing API-functies aanroept om deze toewijzing te doen. Er is behoorlijk wat overhead nodig bij het beheren van dynamisch toegewezen geheugen, wat meestal wordt afgehandeld door de runtime-code van de gebruikte programmeertaal of omgeving.

  • Wat is hun bereik?

    De call-stack is zo’n laag concept dat het geen betrekking heeft op ‘scope’ in de zin van programmeren. Als je wat code uit elkaar haalt, zie je relatieve verwijzingen in aanwijzerstijlen naar delen van de stapel, maar voor zover het een taal op een hoger niveau betreft, legt de taal zijn eigen regels op voor de reikwijdte. Een belangrijk aspect van een stapel is echter dat zodra een functie terugkeert, alles wat lokaal is voor die functie onmiddellijk van de stapel wordt bevrijd. Dat werkt zoals je zou verwachten dat het werkt, gegeven hoe je programmeertalen werken. In een hoop, het is ook moeilijk te definiëren. Het bereik is alles wat door het besturingssysteem wordt blootgelegd, maar uw programmeertaal voegt waarschijnlijk zijn regels toe over wat een “bereik” is in uw toepassing. De processorarchitectuur en het besturingssysteem gebruiken virtuele adressering, die de processor vertaalt naar fysieke adressen en er zijn paginafouten, enz. Ze houden bij welke pagina’s bij welke applicaties horen. U hoeft zich hier echter nooit echt zorgen over te maken, want u gebruikt gewoon de methode die uw programmeertaal gebruikt om geheugen toe te wijzen en vrij te maken, en controleert op fouten (als het toewijzen/vrijmaken om welke reden dan ook mislukt).

  • Wat bepaalt de grootte van elk van hen?

    Nogmaals, het hangt af van de taal, compiler, besturingssysteem en architectuur. Een stack is meestal vooraf toegewezen, omdat het per definitie aaneengesloten geheugen moet zijn. De taalcompiler of het besturingssysteem bepaalt de grootte. U slaat geen grote hoeveelheden gegevens op de stapel op, dus deze is groot genoeg om nooit volledig te worden gebruikt, behalve in gevallen van ongewenste eindeloze recursie (vandaar “stack-overflow”) of andere ongebruikelijke programmeerbeslissingen.

    Een heap is een algemene term voor alles dat dynamisch kan worden toegewezen. Afhankelijk van hoe je het bekijkt, verandert het constant van formaat. In moderne processors en besturingssystemen is de exacte manier waarop het werkt sowieso erg geabstraheerd, dus je hoeft je normaal gesproken niet veel zorgen te maken over hoe het diep van binnen werkt, behalve dat je (in talen waar het je toestaat) geen geheugen mag gebruiken dat je hebt nog geen geheugen toegewezen of hebt vrijgemaakt.

  • Wat maakt iemand sneller?

    De stapel is sneller omdat al het vrije geheugen altijd aaneengesloten is. Er hoeft geen lijst te worden bijgehouden van alle segmenten van het vrije geheugen, alleen een enkele verwijzing naar de huidige bovenkant van de stapel. Compilers slaan deze pointer voor dit doel meestal op in een speciaal, snel register. Bovendien zijn daaropvolgende bewerkingen op een stapel meestal geconcentreerd in zeer nabije geheugengebieden, wat op een zeer laag niveau goed is voor optimalisatie door de processor-on-die-caches.


4, Autoriteit 7%

In de volgende C #–code

public void Method1()
{
    int i = 4;
    int y = 2;
    class1 cls1 = new class1();
}

Hier is hoe het geheugen wordt beheerd

Local Variablesdie alleen maar moeten duren zolang de functie-aanwijzing in de stapel gaat. De hoop wordt gebruikt voor variabelen waarvan we leven niet echt voor de voorkant kennen, maar we verwachten dat ze een tijdje duren. In de meeste talen is het van cruciaal belang dat we weten bij compileertijd hoe groot een variabele is als we het op de stapel willen opslaan.

Objecten (die in grootte variëren zoals we ze updaten) gaan op de hoop omdat we niet weten bij de scheppingstijd hoe lang ze duren. In veel talen is de heap afval opgehaald om objecten te vinden (zoals het CLS1-object) dat niet langer referenties heeft.

In Java gaan de meeste objecten rechtstreeks in de hoop. In de talen zoals C / C++ kunnen erkent en klassen vaak op de stapel blijven wanneer u niet met Pointers te maken hebt.

Meer informatie is hier te vinden:

Het verschil tussen stapel en heap geheugen toewijzing «timmurphy.org

en hier:

Objecten maken op de stapel en de heap

Dit artikel is de bron van foto hierboven: zes belangrijke .NET-concepten: stapel, heap, value types, referentietypen, boksen en unboxing – codeproject

Maar wees bewust dat het enkele onnauwkeurigheden kan bevatten.


5, Autoriteit 3%

de stapel
Wanneer u een functie noemt, wordt de argumenten in die functie plus een andere overhead op de stapel geplaatst. Enkele info (zoals waar te gaan, wordt daar ook opgeslagen.
Wanneer u een variabele in uw functie declareert, wordt die variabele ook op de stapel toegewezen.

Deallocating De stapel is vrij eenvoudig omdat u altijd in de omgekeerde volgorde deelt waarin u deelt. Stapel dingen worden toegevoegd terwijl u functies invoert, de bijbehorende gegevens worden verwijderd terwijl u ze afsluit. Dit betekent dat u in de neiging bent om in een klein gebied van de stapel te blijven, tenzij u veel functies belt die veel andere functies oproepen (of een recursieve oplossing maken).

de heap
De heap is een generieke naam voor waar u de gegevens op de vlucht zet. Als u niet weet hoeveel ruimteschepen uw programma gaat maken, gebruikt u waarschijnlijk de nieuwe (of malloc of equivalent) Operator om elk ruimteschip te maken. Deze toewijzing gaat een tijdje rond, dus het is waarschijnlijk dat we dingen in een andere volgorde zullen bevrijden dan we ze hebben gemaakt.

Aldus is de hoop veel complexer, omdat er uiteindelijk gebieden van het geheugen zijn die ongebruikt zijn met stukken met brokken die zijn – het geheugen wordt gefragmenteerd. Het vinden van het vrije geheugen van de grootte die u nodig hebt, is een moeilijk probleem. Dit is de reden waarom de hoop moet worden vermeden (hoewel het nog steeds vaak wordt gebruikt).

implementatie
De implementatie van zowel de stapel als de heap is meestal naar de runtime / OS. Vaak spelen games en andere toepassingen die kritiek zijn, hun eigen geheugenoplossingen creëren die een groot stuk geheugen van de heap pakken en vervolgens intern opduiken om te voorkomen dat het op het besturingssysteem is gebaseerd op het besturingssysteem.

Dit is alleen praktisch als uw geheugengebruik heel anders is dan de norm – d.w.z.e voor games waar u een niveau in één enorme werking laadt en de hele partij in een andere enorme werking kunt schudden.

fysieke locatie in het geheugen
Dit is minder relevant dan je denkt vanwege een technologie genaamd virtueel geheugen waardoor je programma je denkt toegang hebben tot een bepaald adres waarbij de fysieke gegevens ergens anders zijn (zelfs op de harde schijf!). De adressen die u voor de stapel krijgt, zijn in toenemende volgorde omdat uw oproepboom dieper wordt. De adressen voor de heap zijn niet-voorspelbaar (I.E implimentatiespecifiek) en eerlijk gezegd niet belangrijk.


6, Autoriteit 3%

om te verduidelijken, Dit antwoord heeft onjuiste informatie (Thomas opgelost zijn antwoord na reacties, cool :)). Andere antwoorden vermijden gewoon uitleggen welke statische toewijzingsmiddelen betekent. Dus ik zal de drie belangrijkste vormen van toewijzing uitleggen en hoe ze meestal betrekking hebben op de hoop, stapel en gegevenssegment hieronder. Ik zal ook enkele voorbeelden laten zien in zowel C / C++ als Python om mensen te helpen begrijpen.

“Static” (aka statisch toegewezen) variabelen worden niet op de stapel toegewezen. Ga er niet van uit – veel mensen doen alleen omdat “statisch” veel klinkt als “stapel”. Ze bestaan ​​eigenlijk in noch de stapel, noch de hoop. Het maakt deel uit van wat de gegevenssegment .

Het is echter over het algemeen beter om “scope ” en “levenslang ” in plaats van “stapel” en “heap” te overwegen.

Scope verwijst naar welke delen van de code toegang hebben tot een variabele. Over het algemeen denken we aan lokaal bereik(alleen toegankelijk voor de huidige functie) versus algemeen bereik(kan overal worden geopend), hoewel het bereik veel complexer kan worden.

Levensduur verwijst naar wanneer een variabele wordt toegewezen en ongedaan wordt gemaakt tijdens de uitvoering van het programma. Meestal denken we aan statische toewijzing(variabele blijft bestaan gedurende de gehele duur van het programma, waardoor het handig is om dezelfde informatie over meerdere functieaanroepen op te slaan) versus automatische toewijzing(variabele blijft alleen bestaan tijdens een enkele aanroep van een functie, waardoor het nuttig is voor het opslaan van informatie die alleen tijdens uw functie wordt gebruikt en kan worden weggegooid zodra u klaar bent) versus dynamische toewijzing(variabelen waarvan de duur wordt gedefinieerd tijdens runtime , in plaats van compileertijd zoals statisch of automatisch).

Hoewel de meeste compilers en interpreters dit gedrag op dezelfde manier implementeren in termen van het gebruik van stapels, heaps, enz., kan een compiler soms deze conventies breken als hij dat wil, zolang het gedrag maar correct is. Als gevolg van optimalisatie kan een lokale variabele bijvoorbeeld alleen in een register voorkomen of geheel worden verwijderd, hoewel de meeste lokale variabelen in de stapel aanwezig zijn. Zoals in een paar opmerkingen is opgemerkt, staat het je vrij om een compiler te implementeren die niet eens een stapel of een heap gebruikt, maar in plaats daarvan een aantal andere opslagmechanismen (zelden gedaan, omdat stapels en heaps hier geweldig voor zijn).

Ik zal een eenvoudige geannoteerde C-code geven om dit alles te illustreren. De beste manier om te leren is door een programma onder een debugger uit te voeren en het gedrag te bekijken. Als je liever python leest, ga dan naar het einde van het antwoord 🙂

// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;
// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {
    // Statically allocated in the data segment when the program is first loaded
    // Deallocated when the program/DLL exits
    // scope - can be accessed only within MyFunction()
    static int someLocalStaticVariable;
    // Allocated on the stack each time MyFunction is called
    // Deallocated when MyFunction returns
    // scope - can be accessed only within MyFunction()
    int someLocalVariable;
    // A *pointer* is allocated on the stack each time MyFunction is called
    // This pointer is deallocated when MyFunction returns
    // scope - the pointer can be accessed only within MyFunction()
    int* someDynamicVariable;
    // This line causes space for an integer to be allocated in the heap
    // when this line is executed. Note this is not at the beginning of
    // the call to MyFunction(), like the automatic variables
    // scope - only code within MyFunction() can access this space
    // *through this particular variable*.
    // However, if you pass the address somewhere else, that code
    // can access it too
    someDynamicVariable = new int;
    // This line deallocates the space for the integer in the heap.
    // If we did not write it, the memory would be "leaked".
    // Note a fundamental difference between the stack and heap
    // the heap must be managed. The stack is managed for us.
    delete someDynamicVariable;
    // In other cases, instead of deallocating this heap space you
    // might store the address somewhere more permanent to use later.
    // Some languages even take care of deallocation for you... but
    // always it needs to be taken care of at runtime by some mechanism.
    // When the function returns, someArgument, someLocalVariable
    // and the pointer someDynamicVariable are deallocated.
    // The space pointed to by someDynamicVariable was already
    // deallocated prior to returning.
    return;
}
// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.

Een bijzonder aangrijpend voorbeeld van waarom het belangrijk is om onderscheid te maken tussen levensduur en bereik, is dat een variabele een lokaal bereik maar een statische levensduur kan hebben, bijvoorbeeld ‘someLocalStaticVariable’ in het bovenstaande codevoorbeeld. Dergelijke variabelen kunnen onze gewone maar informele naamgevingsgewoonten erg verwarrend maken. Als we bijvoorbeeld “lokaal” zeggen, bedoelen we meestal “lokaal toegewezen automatisch toegewezen variabele” en als we globaal zeggen, bedoelen we meestal “globaal bereikbare statisch toegewezen variabele“. Helaas, als het gaat om zaken als “statisch toegewezen variabelen met een bestandsbereik“, zeggen veel mensen gewoon… “huh???“.

Sommige syntaxiskeuzes in C/C++ verergeren dit probleem – veel mensen denken bijvoorbeeld dat globale variabelen niet “statisch” zijn vanwege de onderstaande syntaxis.

int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation
int main() {return 0;}

Houd er rekening mee dat als u het trefwoord “static” in de bovenstaande declaratie plaatst, wordt voorkomen dat var2 een globaal bereik heeft. Niettemin heeft de globale var1 statische toewijzing. Dit is niet intuïtief! Om deze reden probeer ik nooit het woord “statisch” te gebruiken bij het beschrijven van het bereik, en in plaats daarvan iets te zeggen als “bestand” of “bestand beperkt” bereik. Veel mensen gebruiken echter de uitdrukking “statisch” of “statisch bereik” om een variabele te beschrijven die alleen toegankelijk is vanuit één codebestand. In de context van de levensduur betekent “statisch” altijddat de variabele wordt toegewezen bij de start van het programma en wordt opgeheven wanneer het programma wordt afgesloten.

Sommige mensen beschouwen deze concepten als C/C++-specifiek. Zij zijn niet. Het onderstaande Python-voorbeeld illustreert bijvoorbeeld alle drie de soorten toewijzing (er zijn enkele subtiele verschillen mogelijk in geïnterpreteerde talen, waar ik hier niet op in zal gaan).

from datetime import datetime
class Animal:
    _FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated
    def PetAnimal(self):
        curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
        print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)
class Cat(Animal):
    _FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's
class Dog(Animal):
    _FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!
if __name__ == "__main__":
    whiskers = Cat() # Dynamically allocated
    fido = Dog() # Dynamically allocated
    rinTinTin = Dog() # Dynamically allocated
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()
    Dog._FavoriteFood = 'milkbones'
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()
# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones

7, Autoriteit 3%

Anderen hebben de brede slagen redelijk goed beantwoord, dus ik gooi een paar details in.

  1. Stack en heap hoeven niet enkelvoud te zijn. Een gemeenschappelijke situatie waarin u meer dan één stapel hebt, is als u meer dan één draad in een proces hebt. In dit geval heeft elke draad een eigen stapel. U kunt ook meer dan één hoop hebben, bijvoorbeeld sommige DLL-configuraties kunnen resulteren in verschillende DLL’s die uit verschillende hopen toewijzen, daarom is het over het algemeen een slecht idee om het geheugen van een andere bibliotheek te vrijgeven.

  2. in C U kunt het voordeel krijgen van de toewijzing van variabele lengte door het gebruik van Alloca , die op de stapel toewijst, in tegenstelling tot Alloc, die op de hoop toewijst. Dit geheugen zal uw retourverklaring niet overleven, maar het is handig voor een krasbuffer.

  3. Het is niet gratis om een enorme tijdelijke buffer op Windows te maken waar je niet veel van gebruikt. Dit komt omdat de compiler een stack-probe-lus genereert die wordt aangeroepen telkens wanneer uw functie wordt ingevoerd om te controleren of de stapel bestaat (omdat Windows een enkele beveiligingspagina aan het einde van uw stapel gebruikt om te detecteren wanneer de stapel moet groeien. Als u meer dan één pagina aan het einde van de stapel in het geheugen komt, crasht u). Voorbeeld:

void myfunction()
{
   char big[10000000];
   // Do something that only uses for first 1K of big 99% of the time.
}

Antwoord 8, autoriteit 2%

Anderen hebben uw vraag direct beantwoord, maar als ik de stapel en de heap probeer te begrijpen, denk ik dat het nuttig is om de geheugenlay-out van een traditioneel UNIX-proces te overwegen (zonder threads en mmap()-gebaseerde toewijzers). De webpagina Verklarende woordenlijst geheugenbeheerbevat een diagram van deze geheugenlay-out.

De stapel en heap bevinden zich traditioneel aan weerszijden van de virtuele adresruimte van het proces. De stapel groeit automatisch wanneer deze wordt geopend, tot een grootte die is ingesteld door de kernel (die kan worden aangepast met setrlimit(RLIMIT_STACK, ...)). De heap groeit wanneer de geheugenallocator de systeemaanroep brk()of sbrk()aanroept, waardoor meer pagina’s fysiek geheugen worden toegewezen aan de virtuele adresruimte van het proces.

In systemen zonder virtueel geheugen, zoals sommige embedded systemen, is vaak dezelfde basislay-out van toepassing, behalve dat de stapel en heap een vaste grootte hebben. In andere ingebedde systemen (zoals die op basis van Microchip PIC-microcontrollers) is de programmastapel echter een afzonderlijk geheugenblok dat niet kan worden geadresseerd door instructies voor gegevensverplaatsing, en alleen kan worden gewijzigd of indirect worden gelezen via programmastroominstructies (aanroep, terugsturen, enz.). Andere architecturen, zoals Intel Itanium-processors, hebben meerdere stacks. In die zin is de stapel een onderdeel van de CPU-architectuur.


Antwoord 9, autoriteit 2%

De stapel is een gedeelte van het geheugen dat kan worden gemanipuleerd via verschillende belangrijke instructies in de assembleertaal, zoals ‘pop’ (een waarde uit de stapel verwijderen en teruggeven) en ‘push’ (een waarde naar de stapel duwen), maar ook call (roep een subroutine aan – dit duwt het adres om terug te keren naar de stapel) en return (retourneer van een subroutine – dit haalt het adres van de stapel en springt ernaar toe). Het is het geheugengebied onder het stackpointerregister, dat naar behoefte kan worden ingesteld. De stapel wordt ook gebruikt om argumenten door te geven aan subroutines, en ook om de waarden in registers te bewaren voordat subroutines worden aangeroepen.

De heap is een deel van het geheugen dat door het besturingssysteem aan een toepassing wordt gegeven, meestal via een syscall-achtige malloc. Op moderne besturingssystemen is dit geheugen een verzameling pagina’s waartoe alleen het aanroepende proces toegang heeft.

De grootte van de stapel wordt tijdens runtime bepaald en groeit over het algemeen niet nadat het programma is gestart. In een C-programma moet de stapel groot genoeg zijn om elke variabele te bevatten die binnen elke functie is gedeclareerd. De heap zal naar behoefte dynamisch groeien, maar het besturingssysteem doet uiteindelijk de aanroep (vaak zal de heap groter worden dan de door malloc gevraagde waarde, zodat in ieder geval sommige toekomstige mallocs niet terug hoeven te gaan naar de kernel om krijg meer geheugen. Dit gedrag is vaak aanpasbaar)

Omdat je de stapel hebt toegewezen voordat je het programma start, hoef je nooit te mallocen voordat je de stapel kunt gebruiken, dus dat is een klein voordeel. In de praktijk is het erg moeilijk om te voorspellen wat snel en wat langzaam zal zijn in moderne besturingssystemen met subsystemen met virtueel geheugen, omdat hoe de pagina’s worden geïmplementeerd en waar ze worden opgeslagen een implementatiedetail is.


Antwoord 10, autoriteit 2%

Wat is een stapel?

Een stapel is een stapel objecten, meestal een die netjes is gerangschikt.

Stacks in computerarchitecturen zijn geheugengebieden waar gegevens op een last-in-first-out manier worden toegevoegd of verwijderd.
In een toepassing met meerdere threads heeft elke thread zijn eigen stapel.

Wat is een hoop?

Een hoop is een slordige verzameling dingen die lukraak zijn opgestapeld.

In Computing Architectures is de heap een gebied van dynamisch toegewezen geheugen dat automatisch wordt beheerd door het besturingssysteem of de Memory Manager-bibliotheek.
Geheugen op de hoop is toegewezen, afgehandeld en regelmatig gewijzigd tijdens de uitvoering van het programma, en dit kan leiden tot een probleem dat fragmentatie wordt genoemd.
Fragmentation treedt op wanneer geheugenobjecten worden toegewezen met kleine ruimtes ertussen die te klein zijn om extra geheugenobjecten vast te houden.
Het nettoresultaat is een percentage van de heapruimte die niet bruikbaar is voor verdere geheugenwijzingen.

beide samen

In een applicatie met meerdere schroefdraad heeft elke draad een eigen stapel. Maar alle verschillende draden zullen de hoop delen.
Omdat de verschillende draden de hoop in een multi-threaded-applicatie delen, betekent dit ook dat er enige coördinatie tussen de draden moet zijn, zodat ze niet proberen toegang te krijgen tot en manipuleren van hetzelfde stuk (en) van het geheugen in de heap tegelijkertijd.

die sneller is – de stapel of de hoop? En waarom?

De stapel is veel sneller dan de heap.
Dit komt door de manier waarop het geheugen op de stapel is toegewezen.
Het toewijzen van het geheugen op de stapel is net zo eenvoudig als het verplaatsen van de stapelpointer omhoog.

Voor mensen Nieuws om te programmeren, is het waarschijnlijk een goed idee om de stapel te gebruiken, omdat het gemakkelijker is.
Omdat de stapel klein is, zou u het willen gebruiken als u precies weet hoeveel geheugen u nodig hebt voor uw gegevens, of als u weet dat de grootte van uw gegevens erg klein is.
Het is beter om de heap te gebruiken als u weet dat u veel geheugen nodig hebt voor uw gegevens, of u weet gewoon niet zeker hoeveel geheugen u nodig hebt (zoals met een dynamische array).

Java-geheugenmodel

De stapel is het geheugengebied waar lokale variabelen (inclusief methodeparameters) worden opgeslagen. Als het gaat om objectvariabelen, zijn dit slechts verwijzingen (pointers) naar de daadwerkelijke objecten op de heap.
Elke keer dat een object wordt geïnstantieerd, wordt een stuk heapgeheugen gereserveerd om de gegevens (status) van dat object vast te houden. Aangezien objecten andere objecten kunnen bevatten, kunnen sommige van deze gegevens in feite verwijzingen bevatten naar die geneste objecten.


Antwoord 11, autoriteit 2%

Ik denk dat veel andere mensen je over deze kwestie grotendeels de juiste antwoorden hebben gegeven.

Een detail dat echter is gemist, is dat de “hoop” eigenlijk de “gratis winkel” zou moeten heten. De reden voor dit onderscheid is dat de oorspronkelijke gratis winkel werd geïmplementeerd met een gegevensstructuur die bekend staat als een ‘binominale heap’. Om die reden was het toewijzen van vroege implementaties van malloc()/free() een toewijzing van een hoop. Tegenwoordig zijn de meeste gratis winkels echter geïmplementeerd met zeer uitgebreide gegevensstructuren die geen binominale stapels zijn.


Antwoord 12

Je kunt interessante dingen doen met de stapel. U hebt bijvoorbeeld functies als alloca(ervan uitgaande dat u voorbij de overvloedige waarschuwingen over de use), wat een vorm van malloc is die specifiek de stapel gebruikt, niet de heap, voor geheugen.

Dat gezegd hebbende, stack-gebaseerde geheugenfouten behoren tot de ergste die ik heb meegemaakt. Als je heap-geheugen gebruikt en je overschrijdt de grenzen van je toegewezen blok, heb je een behoorlijke kans om een segmentfout te veroorzaken. (Niet 100%: je blok kan incidenteel aangrenzend zijn aan een ander die je eerder hebt toegewezen.) Maar aangezien variabelen die op de stapel zijn gemaakt altijd aan elkaar grenzen, kan het buiten de grenzen schrijven de waarde van een andere variabele veranderen. Ik heb geleerd dat wanneer ik het gevoel heb dat mijn programma niet meer voldoet aan de wetten van de logica, dit waarschijnlijk een bufferoverloop is.


Antwoord 13

Gewoon, de stapel is waar lokale variabelen worden gemaakt. Elke keer dat u een subroutine oproept, worden ook de programmateller (wijzer naar de volgende machine-instructie) en eventuele belangrijke registers, en soms worden de parameters op de stapel geduwd. Vervolgens worden alle lokale variabelen binnen de subroutine op de stapel geduwd (en van daaruit gebruikt). Als de subroutine klaar is, wordt dat spul allemaal weer van de stapel gegooid. De pc- en registergegevens worden en worden teruggezet waar ze waren zoals ze waren gepoft, zodat je programma zijn gang kan gaan.

De heap is het geheugengebied waaruit dynamische geheugentoewijzingen worden gemaakt (expliciete “nieuwe” of “toewijzen”-aanroepen). Het is een speciale gegevensstructuur die geheugenblokken van verschillende groottes en hun toewijzingsstatus kan bijhouden.

In “klassieke” systemen was RAM zo ingedeeld dat de stapelaanwijzer onderaan het geheugen begon, de heapaanwijzer bovenaan en ze groeiden naar elkaar toe. Als ze elkaar overlappen, heb je geen RAM meer. Dat werkt echter niet met moderne multi-threaded besturingssystemen. Elke thread moet zijn eigen stapel hebben en die kunnen dynamisch worden gemaakt.


Antwoord 14

Van WikiAnwser.

Stapel

Wanneer een functie of een methode een andere functie noemt die in beurt een andere functie, enz. Noemt, blijft de uitvoering van al die functies opgehangen totdat de allerlaatste functie zijn waarde retourneert.

Deze keten van opgeschorte functie-oproepen is de stapel, omdat elementen in de stapel (functie-oproepen) van elkaar afhankelijk zijn.

De stapel is belangrijk om te overwegen in uitzonderingsafhandelings- en draaduitvoeringen.

heap

De heap is gewoon het geheugen dat wordt gebruikt door programma’s om variabelen op te slaan.
Element van de hoop (variabelen) hebben geen afhankelijkheden met elkaar en kan altijd op elk moment willekeurig willekeurig worden toegankelijk.


15

stapel

  • Zeer snelle toegang
  • hoef niet expliciet de variabelen uit te geven
  • Space wordt efficiënt beheerd door CPU, het geheugen wordt niet gefragmenteerd
  • Lokale variabelen alleen
  • limiet op stapelgrootte (OS-afhankelijk)
  • Variabelen kunnen niet worden verkregen

heap

  • Variabelen zijn wereldwijd toegankelijk
  • Geen limiet op geheugengrootte
  • (relatief) langzamere toegang
  • Geen gegarandeerd efficiënt gebruik van ruimte, geheugen kan in de loop van de tijd gefragmenteerd worden als blokken geheugen worden toegewezen, vervolgens bevrijd
  • U moet het geheugen beheren (u hebt de leiding over het toewijzen en bevrijden van variabelen)
  • Variabelen kunnen worden aangepast met RealLOC ()

16

Kortom

Een stapel wordt gebruikt voor statische geheugentoewijzing en een heap voor dynamische geheugentoewijzing, zowel opgeslagen in de RAM van de computer.


In detail

de stapel

De stapel is een “LIFO” (laatste in, first out) -gegevensstructuur, die wordt beheerd en geoptimaliseerd door de CPU behoorlijk nauw. Telkens wanneer een functie een nieuwe variabele verklaart, wordt het “geduwd” op de stapel. Toen elke keer dat een functie uitgaat, duwden alle variabelen op de stapel door die functie, bevrijd (dat wil zeggen, ze worden verwijderd). Zodra een stapelvariabele is bevrijd, is die geheugenregio beschikbaar voor andere stapelvariabelen.

Het voordeel van het gebruik van de stapel om variabelen op te slaan, is dat geheugen voor u beheerd. Je hoeft geen geheugen toe te wijzen met de hand, of het vrij te maken als je het nog geen meer nodig hebt. Wat meer is, omdat de CPU zo efficiënt een stapelgeheugen organiseert, het lezen van en schrijven naar stapelvariabelen is erg snel.

Meer zijn te vinden hier .


de heap

De heap is een regio van het geheugen van uw computer dat niet automatisch voor u wordt beheerd en is niet zo goed beheerd door de CPU. Het is een meer vrij zwevende regio van geheugen (en is groter). Om het geheugen op de heap toe te wijzen, moet u MALLOC () of CALLOC () gebruiken, die zijn ingebouwde C-functies. Nadat u geheugen op de heap hebt toegewezen, bent u verantwoordelijk voor het gebruik van GRATIS () om dat geheugen op te lossen zodra u het niet meer nodig hebt.

Als u dit niet doet, heeft uw programma wat bekend staat als een geheugenlek. Dat wil zeggen, het geheugen op de heap zal nog steeds worden opzij (en zal niet beschikbaar zijn voor andere processen). Zoals we zullen zien in het debuggengedeelte, is er een tool genaamd valgrind die u kan helpen geheugen te detecteren lekken.

In tegenstelling tot de stapel heeft de heap geen grootte beperkingen op variabele grootte (afgezien van de voor de hand liggende fysieke beperkingen van uw computer). Heap-geheugen is iets langzamer om te worden gelezen van en geschreven, omdat men aanwijzingen moet gebruiken om toegang te krijgen tot het geheugen op de heap. We zullen binnenkort over de aanwijzingen praten.

In tegenstelling tot de stapel zijn variabelen die op de heap zijn gemaakt, toegankelijk via een functie, overal in uw programma. Heap-variabelen zijn in wezen wereldwijd in scope.

Meer zijn te vinden hier .


Variabelen die op de stapel zijn toegewezen, worden rechtstreeks opgeslagen op het geheugen en de toegang tot dit geheugen is erg snel en de toewijzing ervan wordt behandeld wanneer het programma is samengesteld. Wanneer een functie of een methode een andere functie noemt die in beurt een andere functie, enz. Noemt, blijft de uitvoering van al die functies opgehangen totdat de laatste functie zijn waarde retourneert. De stapel is altijd gereserveerd in een LIFO-volgorde, het meest recent gereserveerde blok is altijd het volgende blok dat moet worden bevrijd. Dit maakt het heel eenvoudig om de stapel bij te houden, waardoor een blok van de stapel is bevrijd, is niets meer dan het aanpassen van één aanwijzer.

Variabelen die op de heap zijn toegewezen, hebben hun geheugen toegewezen op looptijd en toegang tot dit geheugen is een beetje langzamer, maar de heapgrootte is slechts beperkt door de grootte van het virtuele geheugen. Elementen van de heap hebben geen afhankelijkheden met elkaar en kunnen altijd op elk moment willekeurig willekeurig worden toegankelijk. U kunt op elk moment een blok toewijzen en het op elk moment bevrijden. Dit maakt het veel complexer om bij te houden welke delen van de heap op elk gewenst moment worden toegewezen of gratis.

Je kunt de stapel gebruiken als je precies weet hoeveel data je moet toewijzen voor het compileren, en als het niet te groot is. U kunt de heap gebruiken als u niet precies weet hoeveel gegevens u tijdens runtime nodig heeft of als u veel gegevens moet toewijzen.

In een situatie met meerdere threads heeft elke thread zijn eigen volledig onafhankelijke stapel, maar ze zullen de heap delen. De stapel is draadspecifiek en de hoop is toepassingsspecifiek. De stapel is belangrijk om te overwegen bij het afhandelen van uitzonderingen en het uitvoeren van threads.

Elke thread krijgt een stapel, terwijl er meestal maar één heap is voor de toepassing (hoewel het niet ongebruikelijk is om meerdere heaps te hebben voor verschillende soorten toewijzing).

Als de toepassing tijdens runtime meer heap nodig heeft, kan het geheugen uit het vrije geheugen toewijzen en als de stapel geheugen nodig heeft, kan het geheugen uit het vrije geheugen toewijzen dat voor de toepassing is toegewezen.

Zelfs, meer details worden hieren hier.


Kom nu naar de antwoorden op uw vraag.

In hoeverre worden ze beheerd door het besturingssysteem of de taalruntime?

Het besturingssysteem wijst de stapel toe aan elke thread op systeemniveau wanneer de thread wordt gemaakt. Meestal wordt het besturingssysteem aangeroepen door de taalruntime om de heap voor de toepassing toe te wijzen.

Meer vind je hier.

Wat is hun bereik?

Al gegeven bovenaan.

“Je kunt de stapel gebruiken als je precies weet hoeveel data je moet toewijzen voor het compileren, en het is niet te groot. Je kunt de heap gebruiken als je niet precies weet hoeveel data je nodig hebt op runtime of als u veel gegevens moet toewijzen.”

Meer is te vinden in hier.

Wat bepaalt de grootte van elk van hen?

De grootte van de stapel wordt ingesteld door OSwanneer een thread wordt gemaakt. De grootte van de heap wordt ingesteld bij het opstarten van de toepassing, maar kan groeien naarmate er ruimte nodig is (de toewijzingseenheid vraagt meer geheugen van het besturingssysteem).

Wat maakt iemand sneller?

Stacktoewijzing is veel sneller, omdat het alleen de stackaanwijzer verplaatst. Met geheugenpools kun je vergelijkbare prestaties halen uit heaptoewijzing, maar dat brengt een beetje extra complexiteit en zijn eigen problemen met zich mee.

Bovendien is stack versus heap niet alleen een prestatieoverweging; het vertelt je ook veel over de verwachte levensduur van objecten.

Details zijn hierte vinden .


Antwoord 17

OK,eenvoudig en in korte woorden, ze betekenen bestelden niet besteld…!

Stapel: in stapelitems komen dingen op elkaar te liggen, wat betekent dat het sneller en efficiënter kan worden verwerkt!…

Er is dus altijd een index om naar het specifieke item te verwijzen, ook de verwerking gaat sneller, er is ook een relatie tussen de items!…

Heap: Geen volgorde, verwerking zal langzamer gaan en waarden worden door elkaar gehaald zonder specifieke volgorde of index… er zijn willekeurige en er is geen relatie tussen hen… dus uitvoering en gebruikstijd kan variëren…

Ik maak ook de onderstaande afbeelding om te laten zien hoe ze eruit kunnen zien:


Antwoord 18

stapel, heapen gegevensvan elk proces in virtueel geheugen:


Antwoord 19

In de jaren tachtig verspreidde UNIX zich als konijnen bij grote bedrijven die hun eigen bedrijf rolden.
Exxon had er een, net als tientallen merknamen die in de geschiedenis verloren zijn gegaan.
Hoe het geheugen werd ingedeeld, was ter beoordeling van de vele uitvoerders.

Een typisch C-programma werd plat in het geheugen opgemaakt met
een mogelijkheid om te vergroten door de waarde brk() te wijzigen.
Meestal lag de HEAP net onder deze brk-waarde
en het verhogen van brk verhoogde de hoeveelheid beschikbare heap.

De enkele STACK was typisch een gebied onder HEAP dat een stuk geheugen was
niets van waarde bevatten tot de top van het volgende vaste geheugenblok.
Dit volgende blok was vaak CODE die kon worden overschreven door stapelgegevens
in een van de beroemde hacks van zijn tijd.

Een typisch geheugenblok was BSS (een blok met nulwaarden)
die per ongeluk niet op nul werd gezet in het aanbod van één fabrikant.
Een andere was gegevens die geïnitialiseerde waarden bevatten, inclusief snaren en cijfers.
Een derde was code die CRT (C runtime), hoofd-, functies en bibliotheken bevat.

De komst van virtueel geheugen in Unix verandert veel van de beperkingen.
Er is geen objectieve reden waarom deze blokken zich moeten aansluiten,
of gefixeerd in grootte, of bestelde nu een bepaalde manier.
Natuurlijk, voordat UNIX veelschuwingen was die niet lijden aan deze beperkingen.
Hier is een schema dat een van de geheugenlay-outs van dat tijdperk toont.


20

Een paar cent: denk ik, het zal goed zijn om geheugen grafisch en eenvoudiger te tekenen:

Pijlen – Toon waar groeit stapel en heap, proces stapelgrootte hebben limiet, gedefinieerd in OS, draadstapelgrootte beperkingen door parameters in draad Creëer API meestal. Heap meestal beperkend door de maximale virtuele geheugenformaat van het proces, voor 32-bits 2-4 & nbsp; GB bijvoorbeeld.

Zo eenvoudige manier: proceshoop is algemeen voor proces en alle discussies binnen, met behulp van geheugentoewijzing in het algemeen geval met zoiets als MALLOC () .

Stack is snel geheugen voor opslag in het algemeen Case-functie retourwijzers en variabelen, verwerkt als parameters in functie-oproep, lokale functievariabelen.


21

Ik heb iets te delen, hoewel de belangrijkste punten al gedekt zijn.

stapel

  • Zeer snelle toegang.
  • opgeslagen in RAM.
  • Functie-oproepen worden hier geladen, samen met de lokale variabelen en functieparameters die zijn geslaagd.
  • Space wordt automatisch vrijgemaakt wanneer het programma uit een scope stroomt.
  • opgeslagen in sequentieel geheugen.

heap

  • Slow Access Relative to Stack.
  • opgeslagen in RAM.
  • Dynamisch gemaakte variabelen worden hier opgeslagen, die later na gebruik het toegewezen geheugen vereisen.
  • opgeslagen waar geheugentoewijzing is uitgevoerd, altijd toegankelijk via de aanwijzer.

interessant Opmerking:

  • Mocht de functie-oproepen in de hoop zijn opgeslagen, zou het hebben geleid tot 2 rommelige punten:
    1. Vanwege sequentiële opslag in stapel is de uitvoering sneller. Opslag in de hoop zou hebben geleid tot een enorme tijdsverbruik waardoor het hele programma langzamer wordt uitgevoerd.
    2. Als er functies werden opgeslagen in de hoop (rommelige opslag die door de aanwijzer is opgeslagen), zou er geen manier zijn om terug te keren naar het nummer van de beller (welke stapel verschilt vanwege de sequentiële opslag in het geheugen).

Antwoord 22

Wauw! Zoveel antwoorden en ik denk niet dat een van hen het goed had…

1) Waar en wat zijn ze (fysiek in het geheugen van een echte computer)?

De stapel is geheugen dat begint als het hoogste geheugenadres dat aan uw programma-image is toegewezen en vanaf daar in waarde afneemt. Het is gereserveerd voor aangeroepen functieparameters en voor alle tijdelijke variabelen die in functies worden gebruikt.

Er zijn twee soorten: openbaar en privé.

De privéheap begint op een grens van 16 bytes (voor 64-bits programma’s) of een grens van 8 bytes (voor 32-bits programma’s) na de laatste byte code in uw programma en neemt vanaf daar in waarde toe . Het wordt ook wel de standaardheap genoemd.

Als de privé-hoop te groot wordt, overlapt het het stapelgebied, zoals de stapel de hoop overlapt als het te groot wordt. Omdat de stapel op een hoger adres begint en zijn weg naar beneden werkt naar lager adres, met de juiste hacking, kunt u de stapel zo groot maken dat het de privé-heapruimte zal overschrijden en het codegebied overlapt. De truc is dan om genoeg te overlappen van het codegebied dat u in de code kunt haken. Het is een beetje lastig om te doen en je riskeert een programma-crash, maar het is gemakkelijk en zeer effectief.

De openbare heap bevindt zich in zijn eigen geheugenruimte buiten uw programmafbeeldingsruimte. Het is dit geheugen dat op de harde schijf wordt geïnformeerd als geheugenbronnen schaars worden.

2) In hoeverre worden ze gecontroleerd door het besturingssysteem of de taalruntime?

De stapel wordt bestuurd door de programmeur, de privé-hoop wordt beheerd door het besturingssysteem, en de openbare heap wordt niet door iemand gecontroleerd omdat het een OS-service is – u verzoeken en ofwel worden toegekend of geweigerd.

2b) Wat is hun bereik?

Ze zijn allemaal globaal voor het programma, maar hun inhoud kan privé, publiek of wereldwijd zijn.

2c) Wat bepaalt de grootte van elk van hen?

De grootte van de stapel en de privé-heap worden bepaald door uw compiler-runtime-opties. De openbare heap wordt op runtime geïnitialiseerd met behulp van een grootte parameter.

2D) Wat maakt er een sneller?

Ze zijn niet ontworpen om snel te zijn, ze zijn ontworpen om nuttig te zijn. Hoe de programmeur ze gebruikt, bepaalt of ze “snel” of “langzaam” zijn

Ref:

https://norasandler.com/2019/02/ 18 / write-a-compiler-10html

https://docs.microsoft. com/nl-nl/windows/desktop/api/heapapi/nf-heapapi-getprocessheap

https://docs.microsoft. com/nl-nl/windows/desktop/api/heapapi/nf-heapapi-heapcreate


Antwoord 23

Veel antwoorden zijn correct als concepten, maar we moeten er rekening mee houden dat de hardware (d.w.z. de microprocessor) een stapel nodig heeft om het aanroepen van subroutines mogelijk te maken (CALL in assembler..). (OOP-mannen noemen het methoden)

Op de stack bewaar je retouradressen en call → push / ret → pop wordt direct in hardware beheerd.

Je kunt de stapel gebruiken om parameters door te geven.. zelfs als het langzamer is dan het gebruik van registers (zou een microprocessorgoeroe zeggen of een goed BIOS-boek uit de jaren 80…)

  • Zonder stack kan geenmicroprocessor werken. (we kunnen ons geen programma voorstellen, zelfs niet in assembler, zonder subroutines/functies)
  • Zonder de hoop kan het wel. (Een assembleertaalprogramma kan zonder werken, aangezien de heap een OS-concept is, zoals malloc, dat is een OS/Lib-aanroep.

Stackgebruik is sneller als:

  • Is hardware, en zelfs push/pop zijn erg efficiënt.
  • malloc vereist het invoeren van de kernelmodus, gebruik lock/semafoor (of andere synchronisatieprimitieven) om code uit te voeren en enkele structuren te beheren die nodig zijn om de toewijzing bij te houden.

Antwoord 24

De stapel is in wezen een gemakkelijk toegankelijk geheugen dat eenvoudig de items ervan beheert
als een – nou ja – stapel. Alleen items waarvan de grootte van tevoren bekend is, kunnen op de stapel. Dit is het geval voor getallen, strings, booleans.

De hoop is een geheugen voor items waarvan je de niet vooraf kunt bepalen
exacte grootte en structuur
. Omdat objecten en arrays kunnen worden gemuteerd en
veranderen tijdens runtime, ze moeten naar de hoop.

Bron: Academind


Antwoord 25

CPU-stack en -heap zijn fysiek gerelateerd aan hoe CPU en registers werken met geheugen, hoe machine-assemblagetaal werkt, niet de talen op hoog niveau zelf, zelfs als deze talen kleine dingen kunnen beslissen.

Alle moderne CPU’s werken met de “dezelfde” microprocessortheorie: ze zijn allemaal gebaseerd op zogenaamde “registers” en sommige zijn bedoeld om te “stapelen” om prestaties te verbeteren. Alle CPU’s hebben sinds het begin stackregisters en ze waren er altijd al, zoals ik weet. Assemblertalen zijn vanaf het begin hetzelfde, ondanks variaties… tot aan Microsoft en zijn Intermediate Language (IL) die het paradigma veranderde om een OO virtuele machine-assembleertaal te hebben. Dus we zullen in de toekomst wat CLI/CIL CPU kunnen hebben (één project van MS).

CPU’s hebben stapelregisters om de toegang tot geheugens te versnellen, maar ze zijn beperkt in vergelijking met het gebruik van andere registers om volledige toegang te krijgen tot al het beschikbare geheugen voor de processus. Daarom hebben we het gehad over stapel- en heaptoewijzingen.

Samengevat, en in het algemeen, is de heap groot en traag en is bedoeld voor ‘algemene’ instanties en objectinhoud, omdat de stapel klein en snel is en voor ‘lokale’ variabelen en verwijzingen (verborgen aanwijzingen om te vergeten ze te beheren ).

Dus als we het nieuwe sleutelwoord in een methode gebruiken, wordt de referentie (een int) in de stapel gemaakt, maar het object en al zijn inhoud (zowel waardetypes als objecten) wordt in de heap gemaakt, als ik onthouden. Maar lokale elementaire waardetypes en arrays worden in de stapel gemaakt.

Het verschil in geheugentoegang zit op het celverwijzingsniveau: het adresseren van de heap, het algemene geheugen van het proces, vereist meer complexiteit in termen van het verwerken van CPU-registers, dan de stapel die lokaal “meer” is in termen van adressering omdat het CPU-stackregister wordt gebruikt als basisadres, als ik het me goed herinner.

Het is de reden waarom wanneer we zeer lange of oneindige recursieve oproepen of lussen hebben, we snel een stack-overloop hebben, zonder het systeem op moderne computers te bevriezen…

C# Heap (ing) versus stack(ing) in .NET

Stack vs Heap: ken het verschil

Statische klasse geheugentoewijzing waar het is opgeslagen C#

Wat en waar zijn de stack en heap?

https://en.wikipedia.org/wiki/Memory_management

https://en.wikipedia.org/wiki/Stack_register

Bronnen voor montagetaal:

Zelfstudie assembleren

Intel® 64 en IA-32 Architecturen Handleidingen voor softwareontwikkelaars


Antwoord 26

Bedankt voor een heel goede discussie, maar als een echte noob vraag ik me af waar instructies worden bewaard? In het BEGIN waren wetenschappers aan het kiezen tussen twee architecturen (von NEUMANN waar alles als DATA wordt beschouwd en HARVARD waar een geheugengebied was gereserveerd voor instructies en een ander voor gegevens). Uiteindelijk zijn we voor het ontwerp van von Neumann gegaan en nu wordt alles als ‘hetzelfde’ beschouwd. Dit maakte het moeilijk voor mij toen ik assembleren leerde
https://www.cs.virginia.edu/~evans/ cs216/guides/x86.html
omdat ze het hebben over registers en stackpointers.

Alles hierboven gaat over DATA. Mijn gok is dat, aangezien een instructie een gedefinieerd ding is met een specifieke geheugenvoetafdruk, deze op de stapel zou gaan en dus alle ‘die’ registers die in de montage zijn besproken, op de stapel staan. Natuurlijk kwam toen objectgeoriënteerd programmeren met instructies en gegevens die werden samengevoegd tot een structuur die dynamisch was, dus nu zouden instructies ook op de stapel worden bewaard?

Other episodes