[Delphi] vrijgave van geheugen bij interfaces

Pagina: 1
Acties:

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
Al vaak ben ik de volgende code tegengekomen in allerlei varianten:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
procedure Bert;
var
  Ernie: OleVariant; // zomaar een interface
begin
  Ernie := CreateOLEObject('Ernie');
  try
    Ernie.DoeIets;
  finally
    Ernie := Unassigned;
  end;
end;

Daarbij vraag ik me drie dingen af.
  1. Waarom zou je Ernie bij het verlaten van de procedure persé Unassigned willen maken? Die interface wordt toch automatisch opgeruimd zodra hij out of scope raakt?
  2. Stel dat er geen try..finally lus zou zijn en dat Ernie.DoeIets een exception zou raisen. Wordt Ernie dan nog steeds automatisch opgeruimd?
  3. Is Ernie := Unassigned hetzelfde als Ernie := nil?

[ Voor 2% gewijzigd door Tomatoman op 14-07-2003 21:51 . Reden: typo in code ]

Een goede grap mag vrienden kosten.


  • Weng
  • Registratie: Juni 2001
  • Laatst online: 11-05-2024

Weng

Are y'all ready kids

1. Het is gewoon netjes om em te nillen net als nadat je een object hebt gefreed de pointer nillen.

Naar die andere 2 vragen ben ik ook nieuwsgierig.

/Edit:

3. Deze is in de Delphi help op te zoeken. Wat ik ervan begrepen heb is dat het NIET hetzelfde is als nil, maar een variant daarop.

[ Voor 65% gewijzigd door Weng op 14-07-2003 21:48 ]

Aye aye captain


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

1. Ja, maar sommigen willen (onnodig) extra zeker zijn denk ik. Het kan natuurlijk wel helpen als je het al midden in een functie wilt doen.

2. Ja, want de compiler zet er zelf al zo'n try...finally omheen, zonder dat je het ziet.

3. Nee, maar ze geven wel hetzelfde effect. Jouw stukje voorbeeldcode is ook niet helemaal goed. Unassigned gebruik je in het geval van Variants, maar in dit voorbeeld gebruik je een echte interface en moet je dus nil gebruiken. Als je een Variant gebruikt maak je gebruik van late binding en moet het object IDispatch ondersteunen.

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


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
LordLarry schreef op 14 July 2003 @ 21:49:
3. Nee, maar ze geven wel hetzelfde effect. Jouw stukje voorbeeldcode is ook niet helemaal goed. Unassigned gebruik je in het geval van Variants, maar in dit voorbeeld gebruik je een echte interface en moet je dus nil gebruiken. Als je een Variant gebruikt maak je gebruik van late binding en moet het object IDispatch ondersteunen.
Sorry, ik zag de typo ook en had IErnie net veranderd naar OleVariant. Voor het voorbeeld maakt het verder volgens mij niet uit of er van early binding, late binding of een dispinterface gebruik wordt gemaakt.

Een goede grap mag vrienden kosten.


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 17:28

alienfruit

the alien you never expected

1. Dit is gewoon "normaal" je ruimt je gebruikte instances op als je het niet meer nodig hebt.

2. Try-finally loop kun je het beste wle gebruiken, de compiler is zelf zo slim om deze dubbele try-finally loop te negeren. Maar het is wel handig om het toch in je code te plaatsen; weet je iig dat het altijd goed gaat etc.

3. Het is altijd een goed idee om je variable te free-en én te nillen, als je hem allene free-ed dan kun je soms nog problemen krijgen. Je kunt het beste gewoon FreeAndNil() gebruiken. Dit word ook geadviseerd door Borland zelf.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

alienfruit is duidelijk iemand van het andere kamp :)

1. Als het voor me gedaan wordt is het toch ook gedaan? Waarom er extra code aan besteden? Meer typen is meer kans op fouten (wat als je m toch daarna gaat gebruiken?), meer kans op RSI en de compiler genereerd meer code wat het programma dus groter en langzamer maakt. Alleen als het zinnig is dat het midden in de functie moet gebeuren zie ik er nut in.

2. De dubbele try finally loop wordt helaas niet of nauwelijks genegeerd voor zover ik kan zien. En bovendien is het nutteloos om dezelfde redenen als bij 1.

3. Interfaces kan je niet Freeen en dus ook geen FreeAndNil gebruiken, dit in tegenstelling tot objecten waar dit wel nodig en netjes is.

Kortom: Extra, extra, extra zeker is gewoon ruim overbodig in deze gevallen IMHO :) Je moet ook wel wat vertrouwen in de compiler kunnen leggen.

PS: try...finally is geen loop :)

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


Verwijderd

tomatoman schreef op 14 July 2003 @ 21:33:
• Waarom zou je Ernie bij het verlaten van de procedure persé Unassigned willen maken? Die interface wordt toch automatisch opgeruimd zodra hij out of scope raakt?
Ja, maar nu bepaal jij expliciet dat 'ie out of scope raakt, en niet het OLE mechanisme.
Maakt nu niet meer zo gek veel uit, omdat (D)COM 't onder een recent Windows OS een stuk beter doet dan bij de introductie van OLE onder Win95, maar 't kan geen kwaad. In de toekomst zul je dit expliciet free-en steeds minder tegenkomen denk ik, omdat programmeurs dan bv. steeds meer gewend zijn aan C#, etc.
• Stel dat er geen try..finally lus zou zijn en dat Ernie.DoeIets een exception zou raisen. Wordt Ernie dan nog steeds automatisch opgeruimd?
Bij simpele CreateOLEObject acties wel, maar bij CreateRemote (DCOM) is 't wel prettig dat de compiler er zelf al een try/finally omheen zet, en dat 't steeds moeilijker wordt om door een exception in je remote object DCOM plat te krijgen. :)

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op 14 July 2003 @ 22:27:
Ja, maar nu bepaal jij expliciet dat 'ie out of scope raakt, en niet het OLE mechanisme.
Maakt nu niet meer zo gek veel uit, omdat (D)COM 't onder een recent Windows OS een stuk beter doet dan bij de introductie van OLE onder Win95, maar 't kan geen kwaad. In de toekomst zul je dit expliciet free-en steeds minder tegenkomen denk ik, omdat programmeurs dan bv. steeds meer gewend zijn aan C#, etc.
Met het OLE mechanisme bedoel je Reference Counting neem ik aan?

Reference Counting werkt omdat de programmeurs op de juiste plaatsen AddRef en Release aanroepen. Zodra de refcount 0 is wordt het object vrijgegeven. Gelukkig hoeven de Delphi programmeurs niet zelf overal AddRef en Release neer te zetten en doet de compiler dat. In het voorbeeld wordt de Release alleen iets eerder aangeroepen dan dat de compiler het zou doen (aan het einde van de functie), maar verder is het gewoon hetzelfde. Overgens betekend het aanroepen van Release nog niet automatisch dat het object wordt vrijgegeven. Dat wordt dus alleen gedaan als de refcount 0 is.

Ook is het niet de taak van windows (COM/OLE) om de objecten vrij te geven. Het enige wat COM bied zijn wat interfaces, de implementaties moet men zelf maken. Zo ook de implementatie voor IUnknown die o.a. zorgt voor het Reference Counting. Delphi heeft al een standaard implementatie voor je klaarliggen met de naam TComObject. Het vrijgeven heeft dus niets met de windows versie van doen in het geval van COM. DCOM is iets anders omdat dit (mogelijk) over een netwerk gaat waarbij de communicatie nog wel eens een probleem kan zijn.
Delphi:
1
2
3
4
5
6
7
function TComObject.ObjRelease: Integer;
begin
  // InterlockedDecrement returns only 0 or 1 on Win95 and NT 3.51
  // returns actual result on NT 4.0
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then Destroy;
end;
Bij simpele CreateOLEObject acties wel, maar bij CreateRemote (DCOM) is 't wel prettig dat de compiler er zelf al een try/finally omheen zet, en dat 't steeds moeilijker wordt om door een exception in je remote object DCOM plat te krijgen. :)
Zelfs bij CreateOLEObject heb je kans dat je stiekem staat te praten via DCOM met een object op een andere server. Het is een kwestie van configureren in het registry. :) Bovendien is het bij elke exceptie wel prettig dat er evengoed een Release aangeroepen wordt als dit nodig is, DCOM of niet.

[ Voor 11% gewijzigd door LordLarry op 14-07-2003 22:58 ]

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

Pagina: 1