Dereferentie van objecten in destructoren

Status
Niet open voor verdere reacties.

ronaldBe1955

Gebruiker
Lid geworden
10 aug 2008
Berichten
14
Hallo iedereen,

Ik zit als beginner met een paar probleempjes, waaronder het volgende :

C# heeft een garbage collector die alle objecten waarnaar niet meer verwezen wordt automatisch verwijdert (net zoals Java trouwens). In het boek van Microsoft haalt men ook de functie Dispose() aan en de mogelijkheid om garbage collection aan te vragen. Tevens vermeldt men de mogelijkheid om deze functie in een destructor te gebruiken en volgt er een uitleg over IDisposable.

Is het echter mogelijk om de toewijzing van geheugenruite aan een object ongedaan te maken (dereferentie) door simpelweg de variabele op null te zetten zoals hieronder in rood?

Class myClass
{

...

}

MyClass test = new myClass()

....

test = null;


Hartelijk dank bij voorbaat.

Ronald
 
Als je iets op null zet gebeurt volgens mij het volgende (weet het niet zeker):

Je geeft aan dat dit gedeelte van het geheugen opgeruimd kan worden.
De GB zal dit dan ook doen. Echter zal de GB gaan werken wanneer deze dat zelf nodig acht en kan het dus wezen dat dat een tijdje duurt. Hij heeft een lage prioriteit ebn zal pas aangeroepen worden wanneer er tijd is.
 
Null is een literaal die een object definieerd dat geen referenties heeft. Hierdoor zal het inderdaad door de garbage collection worden opgeruimd omdat het object geen zinnige betekenis meer heeft. Je kan dus in theorie geheugenruimte gaan vrijmaken door objecten gelijk te stellen aan null.

De garbage collection kan omschreven worden als een managed mermory allocation engine. Ze gaat dus geheugen toekennen aan het programma wanneer een nieuw object wordt aangemaakt (door bijvoorbeeld het new keyword) en gaat een 'collection' (opruiming) doen van objecten die geen nut meer hebben (out of scope) of die geen referenties meer hebben.

Een object gelijk stellen aan null heeft soms tot gevolg dat het object wordt opgeruimd door de garbage collection, maar dit is niet altijd zo. (ga niet te fel uitwijden) Daarom is het gelijkstellen aan null geen garantie tot het vrijmaken van geheugen. De beste manier om dit wel te doen is de scope van je object zo te definiëren dat ze automatisch door de garbage collection wordt opgeruimd.(protected, functie objecten,...) Dit kan eventueel gecombineerd worden met het forceren van de garbage collection (al hoe wel dat zelden tot nooit nodig is)

Code:
 GC.Collect();
 GC.WaitForPendingFinalizers();

Hierbij ga je via de collection() methode de garbage collection forceren. Hierna kan je de WaitForPendingFinalizers() methode gebruiken zodat de huidige thread zijn prioriteit afgeeft aan de thread die bepaald welke objecten opgeruimd mogen worden.

Als laatste zou ik je willen meegeven dat een destructor enkel gebruikt moet worden wanneer je unmanaged code in je managed omgeving(.net) gebruikt en in alle (en dan ook echt alle) andere gevallen is dit onnodig.

Als je dit dan toch ooit nodig gaat hebben ga je een destructor op deze manier gebruiken:

Code:
class Test
{
    ~Test()
    {
        System.Diagnostics.Trace.WriteLine("Test destructor is called.");
    }
}

Maar een destrucor kan enkel gebruikt worden in een klasse en dus niet in andere constructies, kan slechts 1 destructor hebben, kan niet worden overerfd of gebruikt via overloading en kent geen argumenten. Een destructor kan niet worden opgeroepen maar worden automatisch invoked wanneer de garbage collection het object opruimt. Een destructor wordt maw uitgevoerd wanneer je object verdwijnt.

Succes
 
Laatst bewerkt:
dereferentie van objecten : belangrijke details

Hallo leden,

Alvast hartelijk bedankt!!!

Bij de laatste reactie heb ik nog drie vraagjes :

- Werkt het niet altijd omdat de garbage collector maar af en toe aangeroepen wordt (zoals de eerste reactie terecht opmerkt) of is er een andere reden? Kan ik er zeker van zijn dat het null-object altijd door de garbage-collector wordt opgeruimd indien hij effectief wordt aangeroepen. Dit lijkt onbelangrijk, maar de garbage-collector wordt altijd aangeroepen bij low memory denk ik.

- De scope bepaalt of een variabele op een bepaalde plaats gezien wordt of niet. Als mijn programma in een plaats buiten de scope zit wordt de variabele niet gezien. Is de pointer dan nog geldig voor de garbage-collector (ik vermoed ongeldig voor private, geldig voor public) ?

- Veronderstel : ik gebruik een gedefinieerde klasse of struct als onderdeel van een andere klasse (zonder overerving). Wordt die klasse of struct dan automatisch opgeruimd als de andere klasse wordt opgeruimd. Zo nee, hoe moet ik die vernietigen (met een destructor of anders)?

Alvast bedankt,

Ronald
 
- Een object gelijkstellen aan null gaat nooit de oorzaak zijn van garbage collection. Door een object gelijk te stellen aan null worden de referenties naar dat object verwijderd waardoor de garbage collection het object in de collection queu gaat opnemen en uiteindelijk gaat verwijderen. In principe zou er nooit een literaal gebruikt moeten worden om garbage collection te veroorzaken. (uitstekende blog post) Je kan gewoon stellen dat de null literaal niets maar dan ook niets met GC te maken heeft. Verder is memory management != garbage collection. Het is niet zo dat de GC vrijgemaakt geheugen onmiddelijk teruggeeft aan het OS maar de GC houdt dit geheugen beschikbaar voor het process waarin ze actief is. De Garbage collection wordt zeer frequent op basis van algoritmes opgeroepen (uitstekend artikel van msdn). Als je meer informatie wil rond GC en memory management kan je best eens op msdn of op andere gespecialiseerde websites kijken dir vaak zeer technisch onderbowude artikels aanbieden.

- Wanneer eender welk object met eender werlke namespace uit scope gaat wordt hij door de garbage collection opgeruimd.

- bv. In klasse A zit een object van klasse B. In klasse C leggen we een referentie naar klasse A volgens de modifier (B.A). Wanneer we de referenties naar klasse B verwijderen zal deze niet meer beschikbaar zijn. De referentie naar klasse A, die we in klasse C maakte, blijft wel bestaan. Deze moet op zijn beurt niet verwijderd of vernietigd worden maar wordt automatisch opgeruimd nadat ze uit scope gaat of geen referenties meer heeft. (bv. uit de functie, klasse C heeft geen referenties meer)

Uiteindelijk is de garbage collection van .net een ongelooflijk ingewikkeld verhaal dat zo ontworpen is om de best mogelijke prestatie te leveren. De werking ervan kennen is altijd een pluspunt MAAR excessief forceren van de GC gaat leiden tot problemen. De GC werkt zo dat hij steeds op het 'juiste' moment gaat opruimen en op dat moment een specifiek aantal object gaat opruimen. (leuk GC artikel)

Ik hoop dat dit antwoorden op uw vragen waren.

succes
 
garbage collection.. bijna door deze hap?

Hallo leden.

Hartelijk bedankt voor de uitleg + posts. 't Lijkt me een ingewikkeld verhaal... Als je de eerste en tweede zin naast elkaar zet lijkt het tegenstrijdig. Mag ik het zo stellen :

- Null gebruiken veroorzaakt geen onmiddellijke GC maar maakt het object wel beschikbaar voor GC op het moment dat die uitgevoerd wordt. De uitvoering van de GC loopt los van het gebruik van de null-pointer.

- GC geeft geen geheugen terug aan het OS maar houdt het beschikbaar voor de applicatie.

- Als een klasse geen referentie meer heeft hebben de klassen die er een onderdeel van zijn ook geen referentie meer, zonder destructor of using () te gebruiken. De klassen die er een onderdeel van zijn worden met de klasse mee opgeruimd, niet alleen de referentie maar ook het geheugen dat ze innemen.

Sorry voor de langdradige post, maar i.v.m. geheugenlekken lijkt dit essentieel. Een deelklasse die niet opgeruimd wordt blokkeert het geheugen dat ze inneemt voor de rest van de applicatie.

Ik heb sterk het gevoel dat er iets essentieel is dat ik nog steeds niet beetheb.

Hartelijk dank.

Ronald
 
- Inderdaad, null kan naast bv. true/false literalen gezet worden.
- Klopt.
- Alleen als er een expliciete referentie wordt gelegd naar een object van een klasse B die onderdeel is van een klasse A blijft dat object bestaan (in de referentie) wanneer die klasse A zijn referenties veliest.

Geheugenlekken in .Net zijn theoretisch niet mogelijk. Enkel slecht gebruik van objecten (oneindige loop, circulaire referenties), slechte scopes (static), overmatig forceren van de GC kunnen tot geheugenproblemen leiden maar nooit tot geheugenlekken. Ik heb zo het vermoeden dat je c# te fel met unmanged programmeeromgeving als c/c++ vergelijkt en dat is iets wat je beter niet doet. Daar c/c++ er vanuit gaat dat je in staat bent geheugen op een goede en performante manier te gebruiken via pointers ed, gaat de c# omgeving er net van uit dat de programmeur van de geheugentoekenning afblijft. IK heb al vrij grote (100000 regels code) projecten in c# gemaakt en ik heb nog nooit problemen gehad met het geheugen of in een situatie gekomen waarbij ik geheugenmanagement zou moeten bijsturen. Als je de OOP- en programmeerstandaarden navolgt zou je normaal nooit in de problemen moeten komen.

Ik hoop dat je er wat mee bent.

succes
 
weeral een stap dichter...

Hallo leden,

Hartelijk bedankt voor de uitleg. Ik heb een consoleprogramma gemaakt dat een en ander uittest (door schrijfinstructies naar de console in de destructor te zetten) Als je een subklasse definieert als onderdeel van een hoofdklasse :

- wordt ze niet mee verwijderd als je ze in de constructor koppelt aan een bestaand object dat je als parameter meegeeft
- wordt ze wel mee verwijderd als je ze in de constructor creeert met new

Verder bestaat er blijkbaar geen Dispose() die je in eigen klassen kunt gebruiken (vind die toch niet) maar misschien zit deze noodzakelijke functionaliteit in de garbage collector?

We zijn er bijna (OEF !!! ). Nu nog een enkel puntje : gebeurt de verwijdering ook als je geen destructoren definieert (en ook geen IDisposible uiteraard)?

Nogmaals hartelijk dank voor alle hulp.

Groetjes,

Ronald
 
Een nuttig artikel...

Hallo,

Hartelijk bedankt voor de link... Een zeer nuttig artikel. 't Komt overeen met wat in het handboek staat. Alleen is Microsoft enkele belangrijke details vergeten :mad: Gewoon ter bevestiging : mag ik het zo samenvatten?

- Gebruik IDisposable in je klasse en in je subklasse
- Maak een wrapperklasse voor je resource (zoals de subklasse in mijn posting)
- Een Dispose() moet gewoon de handle van de subklasse op -1 zetten?

Hartelijk dank.

Ronald
 
Hallo,

Hartelijk bedankt voor de link... Een zeer nuttig artikel. 't Komt overeen met wat in het handboek staat. Alleen is Microsoft enkele belangrijke details vergeten :mad: Gewoon ter bevestiging : mag ik het zo samenvatten?

- Gebruik IDisposable in je klasse en in je subklasse
- Maak een wrapperklasse voor je resource (zoals de subklasse in mijn posting)
- Een Dispose() moet gewoon de handle van de subklasse op -1 zetten?

Hartelijk dank.

Ronald

Inderdaad dit kan je doen, maar als je het niet doet zal de gc deze ook opruimen als je expliciet de referenties verwijdert.
 
nu alleen nog objecten indelen...

Hallo allemaal,

Ik denk dat ik erdoor ben... Klopt het dat mijn klassen, interfaces, structuren en primitieve variabelen "managed memory" zijn en al de rest (handles bv. ) niet? Zijn arrays managed of unmanaged?

Hartelijk dank,

Ronald

P.S. hoe zet je een item op "opgelost"?
 
Arrays zijn ook managed. In principe zijn alle objecten en klassen die niet gebruikmaken van 'native' code managed. (wat wil zeggen dat alle geheugenbeweer wordt behandeld door de GC).
 
De laatste details...

Hallo leden,

Arrays zijn ook managed. In principe zijn alle objecten en klassen die niet gebruikmaken van 'native' code managed.

Die arrays was ik dus gewoon vergeten.. Bedoel je met de laatste zin : alles dat geen inline instructies gebruikt?

Inderdaad dit kan je doen, maar als je het niet doet zal de gc deze ook opruimen als je expliciet de referenties verwijdert.

OK, maar hoe verwijder je de referenties?

Hartelijk bedankt,

Ronald
 
*.net framework ondersteund geen inline code zoals bv c++.
*door je object gelijk te stellen aan null, je object uit scope te laten gaan of je object te disposen, mits IDisposable.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan