Question

In my source I see and use often a construction like:

with TSQLDataSet.Create(nil) do try
  //Dosomething, get a result from a query.    
finally
  Free;
end;

But I also often see the construction:

with TSQLDataSet.Create(nil) do begin
  //Dosomething, get a result from a query.    
end;

If I create objects with a with contruction, do I need to free them or is that automatic at the end of the with-block?

Was it helpful?

Solution

You need to free.

Because Class.Create is just an expression, and Delphi cannot know which expression the resulting value came from.

You can just read VCL sources - there is always explicit .Free.

And you can think of non-object example:

var r: record .... end;
with r do begin
...
end;

If Delphi tried to free everything at with end - then it would try to free non-object ?

with SomeObjectFactory.GetMeAnObject do begin
...
end;

Here you create object not by constructor, but by some function. And this function is not different from TLabel.Font or TDataSet.FieldByName. Should Delphi free it or not here ?

To avoid the risky guesswork and keep it uniform - with is just with. It is just an alias. Nothing more. It was designed back in 1974 and is does not clone functionality of latest .Net/Scala Using(x){..} constructs.


What you maybe saw were constructs like

with TForm.Create(Application) do ...;
with TLabel.Create(MainForm.Panel1) do ...;

That is very different - that does insert newly created control as belonging to an owner. The owner would free all its owned components when it is freed itself. But that does not use Create(nil). And when it still does - then inside the with block you would see some explicit call, binding the object to some container/parent (though that is very fragile in case of exceptions between .Create and binding).

OTHER TIPS

You need to free the object manually. It is not true that they are freed automatically at the end of the with block. This applies in general. If there is something special with the TSQLDataSet, I do not know.

Delphi (Object pascal), C, C++ and many more 3rd generation languages that aren't managed code gives the responsibility of recycling the memory to the programmer. So, in either case you have to be sure that the gained memory is deallocated anywhere in your code.

The first example you gave assumes that the object you created doesn't need to be alive after the end statement. The second examples assumes that the object is created and passed to an other object to be used after the End statement. So the using object should handle the deallocation of memory.

In managed code environments such as Java VM or .Net applications the memory is handled by the environment. The environment senses when there is no reference to an allocated memory piece and frees it whenever it is suitable for the environment.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top