4

Delphi doesn't have a garbage collector, so coming from a Java background this is a real pain in the neck.

Usually, to destroy some memory I won't use anymore I'd use:

if (SomeMemory <> nil) then
  SomeMemory.Free

What would happen if I don't check for nil before deleting?

Additionally, why someone would want to deal with all this "garbage collecting" by himself? Why among all the compiling options Delphi has, there is no Garbage Collector = true

Diego Rueda
  • 2,226
  • 4
  • 21
  • 41
  • 1
    The `SomeObject.Free` method itself does the `SomeObject <> nil` checking for you. You don't have to do it twice. – TLama Mar 21 '14 at 17:25
  • I saw it on a project I received and I am learning Delphi, I thought it was the way to go. – Diego Rueda Mar 21 '14 at 17:26
  • 7
    *Why among all the compiling options Delphi has, there is no Garbage Collector = true?* I have a question for you. Why can't you disable the garbage collector in Java? – David Heffernan Mar 21 '14 at 17:38
  • 2
    A less flippant response is that for some types of application, a garbage collector places an unwelcome performance constraint on your app. – David Heffernan Mar 21 '14 at 17:46
  • 2
    For global variables (like `var Form1: TForm1`), I suggest you use `FreeAndNil(Form1)`, in order to avoid the problem of having the variable pointing to an invalid reference. – GabrielF Mar 21 '14 at 17:53
  • 1
    @DavidHeffernan I was thinking something similar, but in Delphi's way where you have to clean everything you use wouldn't it make code production, or maintenance much difficult. – Diego Rueda Mar 21 '14 at 18:00
  • First part of your Q doesn't make much sense too (but at least answerable). By "some memory" you clearly meant "some object", raw dynamic memory is a really different story. – Free Consulting Mar 21 '14 at 18:26
  • 2
    [The philosophy behind not using GC as a conscious design choice](http://programmers.stackexchange.com/questions/129530/what-are-the-complexities-of-memory-unmanaged-programming/129555#129555), which I posted (from my perspective as a Delphi developer) on Programmers.SE. This might clear a few things up. – Mason Wheeler Mar 21 '14 at 18:57
  • 2
    @MasonWheeler It's not a "conscious design choice"; it's old tech. Even Wirth himself included GC in Oberon and lamented that people chose to commercialize his "flawed" earlier creations. No language created in the 21st century has neglected to include memory management. This is just something Delphi users invent ad hoc to try to convince themselves that Delphi is still the One True Way. I know because I used to defend the Interface/Implementations, Begin/Ends, and other stuff myself. Anything Delphi didn't have you didn't really need or it was actually better the old way. – alcalde Mar 21 '14 at 20:01
  • 1
    @alcalde You are confusing "not using GC" with "not using any automatic memory management" – Stefan Glienke Mar 21 '14 at 20:05
  • @Stefan: Please don't feed the trolls. Just flag him. – Mason Wheeler Mar 21 '14 at 20:52
  • Why do people keep saying Delphi doesn't have a GC? http://stackoverflow.com/a/4442196/71200 – Kenneth Cochran Mar 21 '14 at 21:00
  • 1
    @MasonWheeler Why? To me he has a valid point - although presented in a bit trollish way though. But sometimes I really miss the Tim Taylor grunt when someone talks about how awesome manual memory management is just to make the point. ;) – Stefan Glienke Mar 21 '14 at 21:10
  • 1
    @DavidHeffernan [-XnoClassGC](http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1009045) ;) – mjn Mar 22 '14 at 09:56
  • @mjn One view of GC is that it is a way to view your machine as having infinite memory. The the collection part of GC is a way to fake infinite memory on a finite machine. `noClassGC` just stops faking! ;-) – David Heffernan Mar 22 '14 at 10:11

4 Answers4

7

The code for TObject.Free looks like this :

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

So there is no need to check for nil. You can still get into trouble if you try to free an uninitialized variable, however, as this will result in an AV. Checking for nil (or Assigned) obviously doesn't help you there either. The compiler will warn you if you try to do this, however.

To answer your second question

Why among all the compiling options Delphi has, there is no Garbage Collector = true

The simple answer is that Delphi does not have such a garbage collector. Certain managed types (like strings, dynamic arrays, etc) implement compiler-managed automatic reference counting, and those objects are automatically freed when their reference counts fall to zero. For all other unmanaged objects it is the responsibility of the developer to appropriately clean up object instances when they are no longer needed.

It's not a question of wanting to have to manage your application's memory, it's just a matter of course that you need to.

J...
  • 30,968
  • 6
  • 66
  • 143
  • On iOS and Android, Delphi objects are compiler-managed types that use ARC. – Remy Lebeau Mar 21 '14 at 22:50
  • @RemyLebeau Is that a firemonkey thing, or is it platform specific? All objects? If you're compiling cross-platform do you have to have `IFDEF`s that conditionally free objects for a windows target? – J... Mar 22 '14 at 00:29
  • 1
    Object ARC is a language feature of the mobile compilers only at this time, not the desktop compilers (though it might in the future). It applies to all `TObject` descendants. Embarcadero has tried to make ARC transparent, by reimplementing `TObject.Free()` and `FreeAndNil()` to work under ARC, and introducing `TObject.DisposeOf()` on all platforms. If you want to write ARC-aware code (and sometimes you may need to), there are `{$DEFINE}`s for that. For the majority of code, you can keep using `Free()` and let ARC handle it as needed. – Remy Lebeau Mar 22 '14 at 01:21
6

Checking for nil before Free is redundant. If the reference is nil, then it's already safe to call Free on it. If the reference isn't nil, then the safety of calling Free on it is unchanged and depends entirely on whether the variable contains a valid reference.

For example:

SomeMemory := nil;
SomeMemory.Free; // This is safe.

SomeMemory := TObject.Create;
SomeMemory.Free; // This is safe
Assert(SomeMemory <> nil);
SomeMemory.Free; // This is an error (EInvalidOperation)

In the first block, we don't check whether the variable is null, and yet the call to Free is perfectly safe. It does nothing. In the second block, we see that the variable remains non-null, but calling Free on it yields an exception.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
4

There is a pretty straight-forward way in Delphi to have (something like) garbage collection: use interface pointers. By using variables of a type ultimately derived from IInterface (or IUnknown which is basically the same thing), Delphi will keep close count of the references, and free/destroy/release the instance when the last reference is removed. Using interface pointers, apart from instance creation and a few other things, is almost identical to using object references.

In Nick Hodges' recent work Coding In Delphi, there's quite a bit on this programming technique, and its relations to abstraction, generics, unit testing and dependency injection.

Also new versions of Delphi for other platforms will have ARC (automatic reference counting) on object references as well, operating like interfaces do now. (Obsoleting the Free method, but that's another story.)

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Stijn Sanders
  • 35,982
  • 11
  • 45
  • 67
  • 1
    Definitely. ARC is the future. Generational Garbage Collection (as in Java and C#) is rubbish, garbage, crap, and should never be added to Delphi. – Warren P Mar 21 '14 at 20:11
  • 1
    Now, now, so negative! I've had one project where ARC wouldn't even cut it, since instances needed to get destroyed forcibly. We'd use 'smart' pointers that get an event raised by the destructor, and a kind of abortable locks when using them asynchronously. I should write a blog post with the details someday... – Stijn Sanders Mar 21 '14 at 20:26
2

You can always consult the documentation in order to answer such a question. Here it is, with my emphasis:

Use Free to destroy an object. Free automatically calls the destructor if the object reference is not nil. Any object instantiated at run time that does not have an owner should be destroyed by a call to Free, so that it can be properly disposed of and its memory released. Unlike Destroy, Free is successful even if the object is nil; if the object was never initialized, Free would not result in an error.

Find a more complete discussion of the issue here: Why should I not use "if Assigned()" before using or freeing things?

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490