Title: Returning Objects from Functions- my thoughts
Question: Should you avoid using functions that create and return objects as there is no direct 'ownership' of the object?
Answer:
Freeing Result Objects from functions
This was requested in the requested articles section by Jeff.C.
This represents my own opinion as a full time Delphi developer (four years experience) with a couple of years of C++ experience. My first reaction was that returning an Object (like a stringlist) from a function was a bad thing because it introduces an object that is potentially unowned and may not get freed. In managing objects you must always consider who owns the object and is responsible for freeing it up. How you create them and use them is less important than ensuring they are freed up.
And considering that all objects are created by calling a Constructor function, you can see that returning objects from a function that creates them is acceptable, so long as you maintain a reference to the object to let it be freed up after use.
You might consider developing an object management framework where every objects is created indirectly through calls to the framework and the framework tracks each object as it is created, manages explicit deletions (your code tells the framework that it no longer needs the object) and deletes any undeleted objects when the framework is destroyed. This approach can be a little inflexible though.
Creating & Freeing a lot of objects repeatedly can cause other problems (see my earlier article http://www.delphi3000.com/article.asp?ID=1414) so you need to be well equipped to detect memory leak bugs. If you are lucky they will cause an access violation when the application terminates. If they dont show up now then they will show up at some time in the future, usually at the worst possible time. I recommend Snoop an excellent free utility for trapping memory errors- you can find it at http://www.rmarsh.com/snoop.html
An Example of Good and Bad use
If you drop a list box and two buttons on a form and connect the two buttons to these event handlers and add the makelist function you can see a leak in action with snoop.
function makelist:tstringlist;
begin
result := tstringlist.create;
result.add('Address 1');
result.add('Address 2');
end;
procedure TForm1.Button1Click(Sender: TObject);
var list : tstringlist;
begin
list := makelist;
listbox1.items.Assign(list);
list.free;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
listbox1.items.Assign(makelist);
end;
Button1 is the correct way- the list is owned by the list variable, and listbox1 manages its own copy. Button2 is naughty the list is unowned by anyone so the stringlist still exists when the application terminates. Running Snoop on these two confirms that Button1 works fine and button 2 leaves the list (and its strings) hanging around.
So remember - avoid untracked objects!