fredrikMedlem sedan dec. 19991 072 inlägg Att GC.n tar hand om Heapen är ju klart....men vad händer med värden som ligger på stacken? När rensas dem?
De flesta Value-datatyperna (såsom integer tex) håller ju (oftast) inte så mycket minnesutrymme. Men en "Structure" är ju tex. också en Value-typ och kan hålla massvis med information.
En string deklarerad i en Structure ligger ju på Heapen men pekaren ligger ju i Structuren och om GC.n inte rensar bort Structuren så bör ju inte String.en heller rensas bort då den "ägs" av structuren.
En arraylist som innehåller flera Structures måste ju "boxa" en Structure vid skrivning/läsning (för att göra om till Referens-typ, tar ju object som datatyp), innebär det att structure.n då fungerar som en referens-typ och därmed rensas av GC.n med?
Eller ligger den fortfarande på stacken, och isf. när rensas den?
Re: Rensning av stack?
fredrik skrev:
En string deklarerad i en Structure ligger ju på Heapen men pekaren ligger ju i Structuren och om GC.n inte rensar bort Structuren så bör ju inte String.en heller rensas bort då den "ägs" av structuren.
Under en garbage collection byggs en graf upp som utgår från alla statiska (globala) objekt och från det som finns i "scopet" följer förstås med eftersom de kommer från Main(). Alla dessa objekt är nåbara och kan inte städas bort. En String som ligger i scopet inkapslad i en struct kommer alltså hamna i den grafen och inte städas bort.
fredrik skrev:
En arraylist som innehåller flera Structures måste ju "boxa" en Structure vid skrivning/läsning (för att göra om till Referens-typ, tar ju object som datatyp), innebär det att structure.n då fungerar som en referens-typ och därmed rensas av GC.n med?
Eller ligger den fortfarande på stacken, och isf. när rensas den?
Boxing innebär att man skapar ett objekt på heapen (av typen System.ValueType) och sedan kopierar datat från value-typen in i objektet på heapen. Value-typen ligger förstås kvar på heapen så länge scopet är aktivt.
fredrikMedlem sedan dec. 19991 072 inlägg Ok, då var det som jag anade då...
..men när rensas structuren bort från stacken? när den går ur scope?
...tack för utredningen!
fredrik skrev:
..men när rensas structuren bort från stacken? när den går ur scope?
Tja, det kan man väl säga. En struct är ju bara en minnesyta på stacken, så det görs egentligen ingen "rensning". När man returnerar från funktionen flyttas bara stackpekaren förbi structen.
fredrikMedlem sedan dec. 19991 072 inlägg
När man returnerar från funktionen flyttas bara stackpekaren förbi structen.
....och vad händer då med värderna på stacken? "flaggas" för borttagning?
Har du några bra länkar på ämnet?
PhorpherMedlem sedan feb. 20002 300 inlägg
fredrik skrev:
När man returnerar från funktionen flyttas bara stackpekaren förbi structen.
....och vad händer då med värderna på stacken? "flaggas" för borttagning?
Har du några bra länkar på ämnet?
Värdena ligger kvar men minnet kan allokeras av andra processer. Därför man kan få riktigt märkliga skräpvärden om man råkar läsa utanför allokerat minne t.ex.
Lite jobbigt att förklara detta i text, men såhär funkar det lite kort. Läs gärna stycket "Functions and Stack" i http://www.codeproject.com/cpp/exceptionhandler.asp, som ger en trevlig beskrivning av hur stacken används. Detta är ett c++ exempel, men ger en bra förklaring om hur en stack fungerar. Exceptionhanteringen är annorlunda implementerad i native C++ jämfört med CLR, men artikeln är lika bra för det.
Det finns liksom inget behov av att "flagga något för borttagning" när det ligger på stacken, det är snarare så att man flyttar en pekare så att det som låg på stacken inte längre används.
Stacken är en linjär adressrymd som en tråd jobbar i. Normalt har man 1 MB att tillgå. Överskrider man det genereras ett stack overflow-exception och det är dåligt.
I ett CPU-register (EBP) för den aktuella tråden ligger en pekare till aktuell stack-frame. När man lägger något på stacken (push:ar), innebär det man minskar (den minskas faktiskt, eftersom stacken normalt växer nedåt, men det är egentligen upp till implementationen) pekaren. När man tar bort något från stacken ökas stack-pekaren.
Det är kompilatorn som lägger ut hanteringen av stacken.
Anta att vi är i funktionen Main(), där du har en lokal variabel av typen byte (=en stack-variabel av typen byte).
När du lägger en byte (struct, UInt16, eller någon annan value-type som du föredrar) på stacken minskas den aktuella trådens stackframe-pekare med 1 byte (eller hur mycket som behövs).
Ropar du på en funktion Foo kommer den (med hjälp av det kompilatorn gjort) push:a sina lokala variabler på stacken (alternativt kan läggas de i CPU-register), dvs stackpekaren minskas. När du sedan returnerar från den funktionen pop:as parametrarna bort från stacken, dvs stack-pekaren ökas, så den återigen pekar ut byte-värdet du har i Main(). De lokala variabler som Foo använde ligger fortfarande kvar i minnet, eftersom ingen har rört den minnesytan, det görs ingen upprensning alls. Men det är fortfarande din tråd som ansvarar för den virtuella adressrymden där variablerna låg.
fredrikMedlem sedan dec. 19991 072 inlägg Tack för all info! Kanon, det är inte alltid inte givet hur allt funkar!