[fpc-devel] Boehm garbage collector for freepascal

Thaddy thaddy at thaddy.com
Tue Nov 16 09:15:55 CET 2010


The rants about finalizers versus destructors in the context of GC are a 
many.
Let me make it clear that these discussions almost invariably presume 
the context of the C(++) language.
The main thing being that C++ allocates objects/classes from the stack 
by default. In Freepascal (in Delphi mode or objfpc mode) 
objects/classes are guaranteed to be allocated from the heap.
In the context of stack allocated objects there is (are many!) a 
conflict between finalizers and destructors which makes them mutually 
exclusive..
In de context of heap allocating languages like Freepascal or Delphi 
these conflicts do not exist, not even in a serialized context.
Those arguments are therefore invalid. Even local objects are from the 
heap in Freepascal, as soon as the object goes out of scope it is marked 
for deletion by the GC
For a good understanding why this is so you have to understand how a 
destructor in object pascal relates to the finalzer as used in the Boehm GC.
The finalizer is called - and only called - if the memory (object) is 
already marked for deletion. This means the memory is technically 
already unreachable.
It is perfectly legal to call a destructor on such an object even in a 
asynchroneous context..


On 16-11-2010 4:12, Hans-Peter Diettrich wrote:
> Thaddy schrieb:
>
>> Actually, I am *calling* the destructor in the finalizer, not copying 
>> it. AFAIK this should take care of it.
>
> IMO destructors and finalizers are mutually exclusive, I remember a 
> note like "Why a garbage collector never should call an destructor", 
> that at least applies to mark-sweep GC.
>
This is *only* true for stack allocated objects like in C++ but 
definitely not for heap allocated objects like in freepascal and Delphi. 
Strongly put: the fact that Freepascal allocates from the heap makes it 
extremely suitable for the GC.
If you read the documentation for the Boehm collector you can deduct 
that. (Also in the context of the Java discussions on the same subject.)
> It should be clear that a destructor, that destroys further (owned) 
> objects, will confuse an mark-sweep garbage collector, since it can 
> invalidate the marks. Consequently all allocated memory areas/objects 
> should be flagged as either managed or unmanaged. Then FreeMem can 
> decide, inside the memory manager, whether the memory block should be 
> released immediately (if unmanaged), or should be marked for later 
> deletion (if managed). Dunno about the concrete Boehm implementation...
>
This is not the case: When the finalizer is called the memory (always 
allocated from the heap) is already outside of the scope of the normal 
program flow and can safely be released by the GC. Mark/sweep will work 
safely.
The Boehm GC is smart enough to "see" the live pointers that nest inside 
the main object.

>> Regarding refcounted strings: the way it is implemented here doesn't 
>> carry any prize for beauty, but it seems to work alright.
>
> That's a different GC model, not mark-sweep. Eventually the un/managed 
> flag has to be extended, into managed-by-refcount and 
> managed-by-mark-sweep.
>
Mark sweep will - empirically, granted - work after f.e. the refcount is 
0, not before. The inner workings of the string mechanism are simply not 
changed. That's mainly why I consider my solution not pretty, btw.
And, frankly, I am not sure, as I wrote before.


>> As Marco stated, and is provided, there is a need for a callback and 
>> that is exactly what Boehm has provided for.
>
> That callback may be intended to perform further *finalization*, not 
> *destruction*, of related objects. The FPC/Delphi Finalize procedures 
> and destructors should not be confused with finalizers in the GC 
> sense. A GC finalizer only should clear (Nil) references to other 
> objects, and possibly mark the object as finalized, what might be done 
> after the callback returns. Then the collector phase of the GC will 
> know which objects really can be removed from memory, and will not 
> have to be taken into account in the next mark phase.
>
For a heap based language there is no conflict between a finalizer and a 
destructor. It is perfectly acceptable to call a destructor in the 
finalizer, because it doesn't touch the stack at all. Eliminating the 
standard " objections" .





More information about the fpc-devel mailing list