One of the most used object-oriented patterns is probably this one:

foo := TFoo.create;
try
  //do something with foo
finally
  foo.free;
end;

It basically means, that if you create an instance of some class and if there is no “owner” who takes care of the new instance’s life cycle, then it is your responsibility to destroy the instance again, as soon as you are done with it.

If you don’t care about freeing the objects you created, then you will get “memory leaks”, i.e. you app will use (possibly a lot) more memory as it should.

The technique above is clear and simple, but what if you have more than one object that is needed in a routine? Line them up?

foo := TFoo.create;
bar := TBar.create;
try
  //do something with foo and bar
finally
  foo.free;
  bar.free;
end;

Looks good, and I see this pattern frequently – but hold on! What happens if there is an exception when TBar is created? Right, foo won’t be destroyed in that case. So maybe handle it like this then:

foo := TFoo.create;
try
  bar := TBar.create;
  try
    //do something with foo and bar
  finally
    bar.free;
  end;
finally
  foo.free;
end;

In theory this would be the correct way, and there are a lot of examples that work like that. But look at the code – right: looks really ugly, esp. if we extend that to even more objects being created. Apart from readability there is also some performance hit: every try-frame needs some extra CPU cycles, which may sum up if your routine is time critical already.

My suggestion is this one:

foo := nil;
bar := nil;
try
  foo := TFoo.create;
  bar := TBar.create;
  //do something with foo and bar
finally
  bar.free;
  foo.free;
end;

Now lets discuss some questions about this pattern:

Didn’t we learn, that calls to “Create” have to be made outside the try-finally block?
No, not really. In fact it doesn’t matter where you create an instance of a class. The first example (which is mentioned in many articles) only suggests this, because it’s easy to do so with just one object.

If TBar.create fails, what happens with its bar.free counter part? Wouldn’t it actually be executed on some not “really created” object?
No, in fact bar.free is special method, which can safely be called even on variables pointing to NIL. Free checks if self<>nil and only then the actual destructor is called.

Why did you initialize fo and bar with NIL?
Because otherwise they might have random values. Esp. if they are declared as local variables. And we need NIL initialized variables so that “free” does not call random code in the case of an exception in one of the create calls.

If TBar.create fails with an exception, wouldn’t be there the chance that some address value would have been written to bar already – so that bar.free would be executed on some half initialized instance?
No, if TBar.Create fails with an exception, then the class function “create” would (like any other function) return NO value at all. bar would keep its original value that is.

  • http://masonwheeler.myopenid.com/ Mason Wheeler

    Very nice. One nitpick, though. Free is *not* a class method, it's an instance method. Otherwise, it couldn't take an instance reference as Self. It's just an instance method that has special code to handle the special case of Self = nil.

  • http://www.monien.net/blog Olaf Monien

    ah, yes you are right. Maybe another time I'll explain the difference between a static and a virtual method and why static methods can be called on nil and that static is not static like in .NET :-)

    Regards / Grüße,
    Olaf Monien
    ——————————————
    EDV-Beratung Monien

    Embarcadero Technology Partner
    Delphi Experts Chairman
    http://www.delphiexperts.net
    http://www.monien.net

    Am 06.07.2010 um 16:50 schrieb Disqus:

  • Roberto

    to answer to your second code segment question.. isn't correct assuming that exceptions are trapped into the finally statement? in this case both obj will be freed.

  • Oleg Zavorotny

    If bar.free raises an exception, would the code still call the destructors for other objects (foo.free in this example)?

  • http://www.monien.net/blog Olaf Monien

    no, if you get an exception in the destructor, then you will be screwed anyway :-)

    Regards / Grüße,
    Olaf Monien
    ——————————————
    EDV-Beratung Monien

    Embarcadero Technology Partner
    Delphi Experts Chairman
    http://www.delphiexperts.net
    http://www.monien.net

    Am 06.07.2010 um 17:10 schrieb Disqus:

  • IL

    The last example vs others hides exception if Tfoo.create fails. May be reraise it in finally part?
    if foo = nil then raise else foo.free

  • http://www.monien.net/blog Olaf Monien

    No – this is a common misunderstanding: try-finally does not hide excpetions. All exceptions in a try-finally will bubble up to the next try-except


    Grüße / Regards,
    Olaf Monien

    Sent via iPhone

    Am 06.07.2010 um 18:42 schrieb “Disqus” <>:

  • Xepol

    The downside is that if bar.free thows an exception (it can happen, particularilly if the object has complex dependancies), foo.free never gets to run.

    Should be safe for simple stuff like TStringList objects tho.

  • IL

    Thank you and you are certainly right. I feel I should read RAD Studio Help topic on exceptions again :)

  • http://profiles.yahoo.com/u/RC5IGERQUEMAER5CANI3SJMBDU Alin

    thank you

  • http://twitter.com/JimMcKeeth Jim McKeeth

    I did a session at CodeRage 08 about handling exceptions in destructors in that situation. Check out http://www.davinciunltd.com/2008/12/delayed-exc… to download the code and the video.

  • Jolyon Smith

    Even better is to use my AutoFree() implementation which removes ALL the try/finally boiler-plate code:

    foo := TFoo.Create;
    AutoFree(@foo);

    bar := TBar.Create;
    AutoFree(@bar);

    This implementation assumes that you are providing an initialised reference, i.e create then register for autofree'ing. I am considering providing an overload which accepts multiple references which would assume that these need to be NIL'd as they are not currently initialised:

    AutoFree([@foo, @bar]);

    foo := TFoo.Create;
    bar := TBar.Create;

    This latter approach would be closest to a language enhancement I suggested which is the ability to decorate object reference variables with the “automated” keyword, to get this behaviour built-in:

    var
    foo: TFoo automated;
    bar: TBar automated;
    begin
    foo := TFoo.Create;
    bar := TBar.Create;
    :
    end;

    Note that “automated” would refer only to automated FREE'ing and initial NIL'ing, not automated construction. This syntax could be extended to member variables to have referenced objects destroyed automatically in an object's destructor (how many times do you overload a destructor JUST to destroy other referenced objects?)

  • http://www.cheapbootsforsale.us ugg boots

    Here elaborates the matter not only extensively but also detailly .I support the
    write's unique louis vuitton bags point.It is useful and benefit to your daily life.You can go those
    sits to know more relate things.They are strongly recommended by friends.Personally
    I feel quite well.

  • http://www.monien.net/blog Olaf Monien

    Where we are back to the discussion if at least an optional Garbage Collector is overdue for Delphi. Code without all this try-finally or similar mess is just easier to maintain. Barry had an interesting talk in this topic at Jim's podcast …


    Grüße / Regards,
    Olaf Monien

    Sent via iPhone

    Am 06.07.2010 um 22:42 schrieb “Disqus” <>:

  • http://www.monien.net/blog Olaf Monien

    Imho raising exceptions in destructors is a bad design. It basically leaves your system in an undefined state. When I don't need an object anymore, I tell it to destroy itself. If it tells now “oh I cannot destroy right now”, what am I supposed to do? Put that object into a list of “currently not destroyable objects” and re-try every 5 minutes?

  • Marjan Venema

    Sounds interesting, do you discuss the implementation of your AutoFree somewhere?

  • Jolyon Smith
  • Jolyon Smith

    It would be nice to have an “automated” decoration for variables in Delphi, but we don't absolutely *need* language support to derive the benefits of *simplified* garbage collection – you can get 80% of the way there (or more) yourself with a little bit of initial effort. Or you could just leverage *my* little bit of effort. I really don't mind. :)

    Sidebar: the term “garbage collection” is misleading… it's not “garbage collection” it's “resource management”, and is something we should all know how to do and be pleased to do effectively. Even the trash man won't come into your home and figure out what is trash… you have to gather it all up and put it out to be collected. Effective Garbage Collection is simply not fully automated!!!

  • http://%/zzcuhsp8 GUY


    Medicamentspot.com. Canadian Health&Care.No prescription online pharmacy.Best quality drugs.Special Internet Prices. Online Pharmacy. Buy drugs online

    Buy:Benicar.Nymphomax.Wellbutrin SR.Seroquel.Female Cialis.Zetia.Advair.Amoxicillin.Lipitor.Lipothin.Cozaar.Prozac.Ventolin.Buspar.Zocor.Aricept.SleepWell.Acomplia.Lasix.Female Pink Viagra….

  • http://www.equines4us.com Horses For Sale

    This syntax could be extended to member variables to have referenced objects destroyed automatically in an object’s destructor (how many times do you overload a destructor.

  • Carlo Sirna

    You are missing the point that exceptions do happen also for things that are not in control of the programmer.
    For example: TFileStream closes the underlying windows file handle in its destructor. Let’s say you used TFileStream on a network share and someone turns brutally off the file server. TFileStream.destroy will SURELY raise an exception and this is not a “bad design issue”. it’s reality, not a design issue.

  • http://www.monien.net/blog Olaf Monien

    Even if TfileStream raises an exception under the condition you described, I would still consider it bad design. What would you do with that exception? Stop freeing the FileStream? The file’s handle is already lost in this situation – and getting rid of the handle is one of the purposes of this destructor. If it would seriously raise an exception here, code logic would majorly break, unless you’d wrap every single free with a try except.


    Grüße / Regards,
    Olaf Monien

    Sent via iPhone

    Am 27.11.2010 um 17:12 schrieb “Disqus” :

  • http://www.webhostings.in Website hosting india

    Sound interesting and helpful tutorial for me.

blog comments powered by Disqus
CodeGear Technology Partner