Toon posts:

[Delphi]memory gebruik

Pagina: 1
Acties:

Verwijderd

Topicstarter
Kan iemand me wat tips geven om het geheugen gebruik van een programma zo klein mogelijk te houden?

Ik gebruik bijvoorbeeld veel Form*.Show;
Als ik verderop in het programma dan weer Form*.Close; gebruik is dat form
dan ook uit het geheugen geladen of is daar een andere functie voor?

Ik merk bv. ook dat mijn progje met 4 MB toeneemt als ik een form heb geopent met TWebBrowser. Als ik dat form weer afsluit blijft het geheugen gebruik even groot. Hoe haal ik het dan weer uit het geheugen?

  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Na TForm.Close kan je eventueel een TForm.Release aanroepen. Die aanroep geeft de geheugenruimte helemaal vrij.

Je moet dan naderhand het form ook weer opnieuw createn als je 'm weer nodig hebt.

Siditamentis astuentis pactum.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Show en Close doen (zonder extra code) niets anders dan het form hiden en showen. Het kost dus niet meer of minder geheugen. Wel betekend het dat je dus altijd alle forms geladen hebt en dus zelfs de forms die je misschien normaal nooit gebruikt. Beetje zonde dus. Verder blijft de status van de forms dus ook behouden en dat is niet altijd gewenst. Zoals reeds gevulde TEdits van de laatste keer.

Beter is het dan ook om elke keer als je een form nodig hebt m te createn en als je klaar bent m weer te freeen. Release gebruik je alleen voor als je in de code van het form zelf zichzelf wil vrijmaken. Anders gewoon Free.

Dat je 4Mb toeneemt en dan niet meer af komt omdat je bij het verkeerde geheugen gebruik zit te kijken. Die jij bekijkt telt ook de cache en de dlls mee. Minimize je app maar en kijk dan nog maar eens hoeveel geheugen die inneemt. Probeer dat ook eens met Delphi32.exe voor de grap :)

Je geheugen wordt waarschijnlijk niet (veel) meer of minder omdat windows dat geheugen nog even voor je vasthoud. Das sneller voor als je het nogmaals nodig hebt.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
ik heb bv een form6, als ik dan
form6.create(application); doe ipv form6.Show; dan krijg ik een foutmelding dat form6 l bestaat. Hoe moet het wel?

  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Form6:=TForm6.Create(blabla)

Net als alle andere creations van objecten. ;)

Siditamentis astuentis pactum.


Verwijderd

Topicstarter
ik snap wat je bedoelt.
Ik in hoofdunit heb ik overal
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
etc.

verwijderd. Pas wanneer ik een form wil openen dan gebruik ik dit:

Application.CreateForm(TForm6, Form6);
Form6.Show;

Dit lijkt allemaal goed te gaan, maar MAAR. Hoe sluit ik dat form nou juist af?
Als ik dit gebruik:

Form6.Free; of
Form6.Destroy;

dan runt het programma wel, maar als ik dan het form afsluit dan krijg ik een foutmelding. Iets met een access violation.

Wat doe ik verkeerd?

Verwijderd

Verwijderd schreef op 09 augustus 2002 @ 23:16:
Ik in hoofdunit heb ik overal
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
etc.

verwijderd.
Dit kan je trouwens ook gewoon in de project options aangeven (of je een form automatisch wilt laten creëren)

Het creëren en het verwijderen van een form is gewoon heel simpel:

code:
1
2
3
4
5
var FormBla: TFormBla

FormBla := TFormBla.Create(Application);

FormBla.Free;

  • Mr.Nobody
  • Registratie: Oktober 2001
  • Niet online
Verwijderd schreef op 09 augustus 2002 @ 23:16:
Dit lijkt allemaal goed te gaan, maar MAAR. Hoe sluit ik dat form nou juist af?
Als ik dit gebruik:

Form6.Free; of
Form6.Destroy;

dan runt het programma wel, maar als ik dan het form afsluit dan krijg ik een foutmelding. Iets met een access violation.

Wat doe ik verkeerd?
gebruik release

Opensource delphi componenten (http://www.delphi-jedi.org)


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Verwijderd schreef op 09 augustus 2002 @ 23:16:
ik snap wat je bedoelt.
Ik in hoofdunit heb ik overal
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
etc.

verwijderd. Pas wanneer ik een form wil openen dan gebruik ik dit:

Application.CreateForm(TForm6, Form6);
Form6.Show;
Door gebruik te maken van Application.CreateForm(TFormClass, FormVariable) maak je de Application de owner van het form. Hey, is dat even makkelijk! Bij het afsluiten van de applicatie gaat de Application over alle forms die hij kent, en freet ze zelf. Hoef jij dus niet naar om te kijken. Hetzelfde geldt voor componenten die je op een form zet (designtime) of aanmaakt met TMyControl.Create(MyForm). MyForm is dan de owner, die verantwoordelijk wordt voor het vrijgeven van de instantie van TMyControl.

  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 27-07 15:54
Ik zal proberen het e.e.a. op een rijtje te zetten.

Application.CreateForm(...) is bedoeld voor je project source. Als je formulier dat het eerste werdt gemaakt door CreateForm wordt gesloten (.Close) wordt je applicatie afgesloten.

met Form1 := TForm1.Create(Self); maak je een nieuwe instantie van TForm1 aan.
Het volgende kan dus ook:
code:
1
2
3
4
5
6
7
8
var f1, f2, f3 : TForm1;
begin
  f1 := TForm1.Create(Self);
  f1.Show;
  f2 := TForm1.Create(Self);
  f2.Show;
  f3 := TForm1.Create(Self);
  f3.Show;

.Destroy moet je niet aanroepen. Destroy is ze zogenaamde 'destructor' (.Create is de 'contructor'). .Free roept de destructor aan.
.Release roept .Free aan zodra je uit je code bent. Dit kan heel nuttig zijn.
Voorbeeld:
Met neme een formulier dat je wil vrijgeven als de gebruiker op een knop drukt. Dat kan niet door .Free. De de methode free wordt uitgevoerd en vervolgens wordt er terug gesprongen naar de plek waar .free werdt aangeroepen. Dit is dan je Button1Click, maar die bestaat niet meet. Je formulier bestaat immers niet meer en je hebt een Access Violation. Release lost dit op. De free wordt dan pas uitgevoerd als je uit je event-code bent (of je roept Application.ProcessMessages aan).

.Close is nuttig als je een formulier modaal wilt weergeven en je wilt weten op welke knop de gebruiker heeft geklikt ofzo. Neem een printvoorbeeld. Formuliertje met een afbeelding en twee knoppen: Print & annuleren.
De eigenschap modalresult van de knop kan je instellen op mrOK en mrNo maar in code kan ook:
code:
1
2
  ModalResult := mrOK;
  Close;

Dat formulier kan je dan als volgt gebruiken:
code:
1
2
3
4
5
  PrintForm := TPrintForm.Create(Self);
  // doe iets
  if PrintForm.ShowModal = mrOK then // je krijgt pas het resultaat als PrintForm gesloten is
    PrintZut;
  PrintForm.Free;

Oh ja, als je dingen aanmaakt in je FormCreate (or whereever) geef dat dan ook vrij! Ik vergeet het zelf ook nog wel een om bijvoorbeeld een TStringList vrij te geven.

Ik hoop dat je er wat aan hebt en dat het duidelijk genoeg is.
Sorry voor de layout :)

  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 27-07 15:54
Toevoeging:
Delphi32 schreef op 09 augustus 2002 @ 23:50:
[...]

Door gebruik te maken van Application.CreateForm(TFormClass, FormVariable) maak je de Application de owner van het form. Hey, is dat even makkelijk! Bij het afsluiten van de applicatie gaat de Application over alle forms die hij kent, en freet ze zelf. Hoef jij dus niet naar om te kijken. Hetzelfde geldt voor componenten die je op een form zet (designtime) of aanmaakt met TMyControl.Create(MyForm). MyForm is dan de owner, die verantwoordelijk wordt voor het vrijgeven van de instantie van TMyControl.
Ookal maak je daar geen gebruik van, dan wordt het nog vrijgegeven. Daar zorgt Windows voor (Win 9x/M.E. hebben wel een paar bugjes).

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Elissen schreef op 10 augustus 2002 @ 00:52:
Toevoeging:
[...]
Ookal maak je daar geen gebruik van, dan wordt het nog vrijgegeven. Daar zorgt Windows voor (Win 9x/M.E. hebben wel een paar bugjes).
Je verhaal hierboven was goed, ik was net van plan nog even het ownership verhaal te benadrukken, maar deze opmerking doet me even reageren.
Het is bij mijn weten absoluut not done om dingen te maken en dan maar af te wachten of je OS die dingen weer opruimt. Sure, ik weet ook wel dat WinNT/2000/XP het geheugen vrijgeven na gebruik, maar dat mag geen reden zijn om mensen bad programming practices aan te smeren (NOFI, het gaat me om het principe).

Het principe van Ownership is juist zo handig, omdat je op een doorzichtige manier duidelijk kan maken wie in jouw applicatie verantwoordelijk wordt gehouden voor het opruimen van je rommel.

[edit]Oeps, de een-na-laatste regel in je voorgaande post zegt hetzelfde, die zag ik over het hoofd (verhaaltje over free-en van TStringList) :)

[ Voor 0% gewijzigd door Delphi32 op 10-08-2002 01:00 . Reden: ik moet beter lezen ]


  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 27-07 15:54
Klopt :). Het vrijgeven via ownership werkt perfect en ik maar daar ook zo vaak mogelijk gebruik van. Ik wilde eigenlijk alleen maar aangeven dat CreateForm niet heilig is (denk aan spalsh-vensters). Echter, het OS moet dat wel goed kunnen. Je applicatie kan ook crashen door invloeden van buitenaf, een netwerkverbinding die er aan gaat. Met name vervelend als je database daar overheen gaat :). Windows moet dan wel alles goed vrij kunnen geven, want zelf kan je dat niet altijd meer vanuit je app.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Delphi32 schreef op 09 augustus 2002 @ 23:50:
[...]
Door gebruik te maken van Application.CreateForm(TFormClass, FormVariable) maak je de Application de owner van het form. Hey, is dat even makkelijk! Bij het afsluiten van de applicatie gaat de Application over alle forms die hij kent, en freet ze zelf. Hoef jij dus niet naar om te kijken. Hetzelfde geldt voor componenten die je op een form zet (designtime) of aanmaakt met TMyControl.Create(MyForm). MyForm is dan de owner, die verantwoordelijk wordt voor het vrijgeven van de instantie van TMyControl.
Dus dat betekend dat ie nog niets is opgeschoten want dan blijven de forms nadat ze eenmaal zijn gecreate altijd in het geheugen blijven. En verder verwacht ik een sloot aan memory leaks als ie ze elke keer blijft createn als ie ze wil laten zien :)

Ik personlijk vertrouw nooit op ownership. Alleen als ik heel lui ben :p
Vertrouw alleen jezelf. Waarom zou je m niet vrij maken als je m niet meer nodig hebt? Waarom wachten? Het is alleen maar vragen om rare fouten en memory leaks. Als je m meteen vrij maakt weet je ook meteen waar de eventuele bug zit. Anders merk je het veel later pas en dan is het veel moeilijker terug te zoeken.

Vooral het dubbel createn en het niet vrijmaken van het geheugen zodra het kan vind ik belangrijke redenen om (bijna) nooit op ownership te vertrouwen.

Verder kan je ook nog een form zichzelf laten freeen zonder release aan te roepen door Action := caFree; aan te roepen in de OnClose. Das vooral handig voor MDI apps.

We adore chaos because we like to restore order - M.C. Escher


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Ik heb lang nagedacht of ik hierop wel wilde reageren, maar ik doe het toch maar.
LordLarry schreef op 10 augustus 2002 @ 11:23:
[...]

Dus dat betekend dat ie nog niets is opgeschoten want dan blijven de forms nadat ze eenmaal zijn gecreate altijd in het geheugen blijven.
Ja, maar mijn ownership verhaal sloot ook aan bij eerdere posts (ik legde uit waarom dat in principe niet fout was). Dynamisch creëren van forms heeft meestal mijn voorkeur, maar daar heeft Elissen al een eind over geschreven.
En verder verwacht ik een sloot aan memory leaks als ie ze elke keer blijft createn als ie ze wil laten zien :)
Onzin. Stel je doet 10 x Application.CreateForm(TForm6, Form6) achter elkaar, dan levert dat nog steeds geen memleak op. De Application ruimt ze bij afsluiten weer netjes op.
Ik personlijk vertrouw nooit op ownership. Alleen als ik heel lui ben :p
Vertrouw alleen jezelf. Waarom zou je m niet vrij maken als je m niet meer nodig hebt? Waarom wachten? Het is alleen maar vragen om rare fouten en memory leaks. Als je m meteen vrij maakt weet je ook meteen waar de eventuele bug zit. Anders merk je het veel later pas en dan is het veel moeilijker terug te zoeken.
Waarom mag je niet vertrouwen op ownership? Dat werkt toch gewoon? Er zijn nou eenmaal situaties waarin je forms wilt laten bestaan zonder dat je precies weet wanneer ze definitief overboord kunnen. Ik heb er nog nooit rare fouten of memory leaks mee gehad.
Vooral het dubbel createn en het niet vrijmaken van het geheugen zodra het kan vind ik belangrijke redenen om (bijna) nooit op ownership te vertrouwen.
Dus het feit dat jij als programmeur rare dingen kan uithalen, is voor jou een argument om een constructie niet te gebruiken? Da's het kind met het badwater weggooien.
Nogmaals, er zijn genoeg situaties te bedenken waarin het een ander laten beheren van door jou gecreëerde objecten een veel handiger constructie is dan het zelf helemaal dichttimmeren.
Verder kan je ook nog een form zichzelf laten freeen zonder release aan te roepen door Action := caFree; aan te roepen in de OnClose. Das vooral handig voor MDI apps.
Dit is een zeer nuttige toevoeging. Die hadden we hier nog niet besproken.

  • Tom-my
  • Registratie: November 2000
  • Laatst online: 19-06 09:25

Tom-my

w03iz0rz

LordLarry schreef op 10 augustus 2002 @ 11:23:
[...]

Dus dat betekend dat ie nog niets is opgeschoten want dan blijven de forms nadat ze eenmaal zijn gecreate altijd in het geheugen blijven. En verder verwacht ik een sloot aan memory leaks als ie ze elke keer blijft createn als ie ze wil laten zien :)
Objecten die je niet meer gebruikt, kan je rustig verwijderen. Dus mocht je een form eigenlijk niet willen verwijderen, dan close je hem gewoon. Blijft het zakie nog wel in het geheugen staan. Heb je hem weer nodig dan show je hem weer, zo voorkom je dus gelijk ook onnodig createn van een form.
Ik personlijk vertrouw nooit op ownership. Alleen als ik heel lui ben :p
Vertrouw alleen jezelf. Waarom zou je m niet vrij maken als je m niet meer nodig hebt? Waarom wachten? Het is alleen maar vragen om rare fouten en memory leaks. Als je m meteen vrij maakt weet je ook meteen waar de eventuele bug zit. Anders merk je het veel later pas en dan is het veel moeilijker terug te zoeken.
Ownership niet vertrouwen? In geval van componentjes die je eenmalig gebruikt voor iets geef ik je gelijk. Maar forms, over het algemeen maakt een programmeur er geen sport van om die te createn en te closen in een programma (zou ik zelfs slecht programmeren vinden :)). Dus daarom zou ik zeggen, doe die wel laten samenhangen met de application.
Vooral het dubbel createn en het niet vrijmaken van het geheugen zodra het kan vind ik belangrijke redenen om (bijna) nooit op ownership te vertrouwen.
Dubbel createn is zeker niet mooi, vrijmaken van geheugen al helemaal niet, maar het is ook programmeren, en niet klooien :). Je moet wel opletten waar je mee bezig bent. Overigens, als je object niet goed free'd krijg je meestal al snel een melding van delphi, dachtik zo uit het hoofd te zeggen?
Verder kan je ook nog een form zichzelf laten freeen zonder release aan te roepen door Action := caFree; aan te roepen in de OnClose. Das vooral handig voor MDI apps.
Jup soms zelfs noodzakkelijk, anders krijg je van die leuke av's :).

"Then there was the man who drowned crossing a stream with an average depth of six inches."


  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 27-07 15:54
FanToom schreef op 10 augustus 2002 @ 20:59:
[...]

Objecten die je niet meer gebruikt, kan je rustig verwijderen. Dus mocht je een form eigenlijk niet willen verwijderen, dan close je hem gewoon. Blijft het zakie nog wel in het geheugen staan. Heb je hem weer nodig dan show je hem weer, zo voorkom je dus gelijk ook onnodig createn van een form.

[...]
Ik denk dat dat afhankelijk is van je situatie. Als het gaat over een formpje wat de gebruiker slechts af en toe zal gebruiken, dan kan je 'm beter pas createn als dat nodig is. Op die manier bespaar je geheugen.
Gaat het om een formulier wat de gebruiker vaak te zien krijgt, dan kan je die beter in het geheugen laten staan. Het showen gaat immers sneller dan createn.

Als (bijna) altijd: afhankelijk van de situatie.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Delphi32 schreef op 10 augustus 2002 @ 20:29:

Onzin. Stel je doet 10 x Application.CreateForm(TForm6, Form6) achter elkaar, dan levert dat nog steeds geen memleak op. De Application ruimt ze bij afsluiten weer netjes op.

Waarom mag je niet vertrouwen op ownership? Dat werkt toch gewoon? Er zijn nou eenmaal situaties waarin je forms wilt laten bestaan zonder dat je precies weet wanneer ze definitief overboord kunnen. Ik heb er nog nooit rare fouten of memory leaks mee gehad.
Je hebt gelijk. Je creeerd 10x een nieuw form en stopt die elke keer in 1 variable. Daar krijg je dus 9 stukken gereserveerd geheugen van die de programmeur niet kan vrijgegeven omdat er geen variable meer is die weet waar ze zijn. Toevallig wil het zo dat de Owner van een Form een lijst bijhoud waar doe allemaal owner van is en is er dus meestal dus niets aan de hand. Zelfs als je als Owner nil opgeeft is er nog niet echts aan de hand, want windows zorgt er dan uiteindelijk wel voor.

Maar ik en vele met mij vinden dit geen goed idee. Als je een punt weet waar je zeker kan zeggen dat je een object niet meer nodig hebt dien je m te FreeAndNillen. Waarom?

- Omdat dit geheugen bespaart. Waarom zou je het niet meteen weggooien?
- Omdat dit op het oog onverklaarbare fouten voorkomt.
- Omdat dit beter is te debuggen. Er wodt meteen de OnDestroy aangeroepen ipv pas veel later als de Owner gedestroyed wordt.

Verder blijft het natuurlijk een keuze van smaak :)
Dus het feit dat jij als programmeur rare dingen kan uithalen, is voor jou een argument om een constructie niet te gebruiken? Da's het kind met het badwater weggooien.
Nogmaals, er zijn genoeg situaties te bedenken waarin het een ander laten beheren van door jou gecreëerde objecten een veel handiger constructie is dan het zelf helemaal dichttimmeren.
Inderdaad, die zijn er zeker. Ik zeg ook niet dat het overal en altijd moet. Ik zeg alleen dat als je er toch zeker van bent , waarom zal je het dan niet doen?

Tja, je kan veel dingen doen, maar of ze verstandig zijn is een 2e. Je hoeft niet te nillen na een free. Maar verstandig is het wel. In iedergeval is het een goede gewoonte. Dat is wat ik bedoel.

Nogmaals: Verder blijft het een keuze van smaak

We adore chaos because we like to restore order - M.C. Escher


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

FanToom schreef op 10 augustus 2002 @ 20:59:
form eigenlijk niet willen verwijderen, dan close je hem gewoon. Blijft het zakie nog wel in het geheugen staan. Heb je hem weer nodig dan show je hem weer, zo voorkom je dus gelijk ook onnodig createn van een form.
Jazeker, dat begrijp ik. Maar de topic starter wilde zijn geheugen gebruik beperken, dus vandaar dat dit me niet erg verstandig lijkt :)

Verder moet je hiermee oppassen dat de 'oude' gegevens niet nog in het form staan. Je kan er niet vanuit gaan dat de 2x de start situatie is zoals jij het ziet in je Delphi IDE. De gegevens blijven in de TEdits staan en de TCheckBox heeft nog de keuze van de keer daarvoor als je er niets aan doet. Dat is in veel gevallen een nadeel.
Ownership niet vertrouwen? In geval van componentjes die je eenmalig gebruikt voor iets geef ik je gelijk. Maar forms, over het algemeen maakt een programmeur er geen sport van om die te createn en te closen in een programma (zou ik zelfs slecht programmeren vinden :)). Dus daarom zou ik zeggen, doe die wel laten samenhangen met de application.
Ik vertrouw wel dat de Delphi programmeurs hun werk wel redelijk gedaan hebben. :) Ze de reply hierboven over wat ik er precies mee bedoel.

Ik snap niet helemaal wat je met het laatste deel bedoelt.
Dubbel createn is zeker niet mooi, vrijmaken van geheugen al helemaal niet, maar het is ook programmeren, en niet klooien :). Je moet wel opletten waar je mee bezig bent. Overigens, als je object niet goed free'd krijg je meestal al snel een melding van delphi, dachtik zo uit het hoofd te zeggen?
Nee, het is niet klooien, maar goed en foutloos programmeren is een kunst. Je kan de kunst op verschillende manieren berijken. 1 is zoals jij voorsteld overal heel erg goed op letten en alles onthouden wat je wel en niet mag doen op welke momenten of je kan defensief programmeren en gewoon zo programmeren zodat je geen fouten _kan_ maken. Dat is wat ik voorstel. Zoals ik in de reply hierboven al uitleg betekend dat niet dat je nooit op Ownership mag rekenen, maar dat je dat niet moet gaan doen als het niet nodig is.

Als je een object niet freeed krijg je geen melding. Er zijn programma's die je melden als je memory leaks hebben. Als er iets fout gaat in een OnDestroy merk je dat meestal wel natuurlijk :) En dan wil je natuurlijk wel weten waarom dat gebeurt. Het tijdstip waarop het gebeurd kan veel vertellen. En dat is nu net wat je moeilijker maakt als je (altijd) op Ownership vertrouwd. Want de fout zou ook in zn geownede objecten kunnen zitten. Als je die geownede objecten meteen had vrijgemaakt op het moment dat je ze niet nodig had had je het op dat moment meteen al geweten.

En nogmaals: Het blijft een kwestie van smaak :)

We adore chaos because we like to restore order - M.C. Escher

Pagina: 1