strange work of GC
Mike Parker via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Feb 7 21:36:16 PST 2015
On 2/8/2015 11:32 AM, FG wrote:
> On 2015-02-08 at 01:20, Mike Parker wrote:
>> In your case, forget destructors and the destroy method. Just
>> implement a common method on all of your objects that need cleanup
>> (perhaps name it 'terminate') and call that. This gives you the
>> deterministic destruction that you want (the same as calling destroy
>> on each object) while avoiding the possibility that the GC can call
>> your cleanup method.
>
> What is wrong with doing all that in a destructor? I don't know if it is
> just an implementation detail, but a destroyed object is either
> zero-filled or reinitialized to the default, so, if implemented
> correctly, it knows whether a cleanup is required (and I'm assuming that
> a model of simple single ownership is used, like in Qt). Therefore it
> should be safe to use destroy to finalize an object and even to put
> destroy in its destructor in order to perform a controlled cascade
> destruction of all the children that require immediate cleanup (ie.
> releasing expensive non-GC resources, closing connections, etc.). The
> main difference with C++ being that you would only force finalization,
> but then let the GC free the memory in its normal fashion.
>
>
>
First, there are no guarantees about when or if a destructor is going to
be called. The fact that the current GC calls the destructors of all
live objects at application shutdown is an implementation detail. If you
want deterministic destruction, you can not rely on destructors.
Second, if you are going to call destroy on every object to clean them
up, then in principle that's fine. But now you have to be careful that
no mistakes slip into the code base, e.g. forgetting to call destroy on
an object that touches GC memory in its destructor.
By separating resource cleanup from object destruction, you get both
deterministic cleanup and more freedom in choosing whether or not to
clean up at all. I used to be obsessive about cleaning up everything at
app exit (my C background, I suppose). These days, I've come around to
the view that it's fine just to let the OS handle it. I put a terminate
method in every class that allocates any sort of resource. If I need to
free those resources at runtime, I call terminate and let the GC worry
about the object when it needs to. At app exit, I only call terminate on
objects that absolutely need to do something before the process exits,
like writing a final message to a log file, or sending a See You Later
packet to a server. Everything else I just let go and leave to the OS to
deal with. There's no reason to do otherwise. In essence, resource
cleanup only happens when and if I say. That just isn't possible if all
cleanup is in destructors. You either have to destroy *every* object
yourself, or be vigilant about which objects you let the GC call
destructors on.
More information about the Digitalmars-d-learn
mailing list