Andrei Alexandrescu:
> class File {
>      FILE * fp;
>      this() { fp = fopen("/tmp/temporary"); }
>      ~this() { fclose(fp); }
> }

I am not expert enough about all this topic, so I try to keep myself out of 
this discussion. Recently I have read this:

>issues with finalizers. The main problem with finalizers and garbage 
>collection is that finalizers generally try to reclaim a non-memory resource 
>(such as a specific file, a file handle, or a network socket) based purely on 
>a memory reclamation policy (generally triggered by later memory allocations). 
>Generally those other resource exhaust well before memory does, then you're 
>out of the resource stuck waiting for garbage collection to notice a 
>particular finalizer needs to be run. A better general rule of thumb is "don't 
>ever use finalizers". Instead always call close inside a finally.<

This means that putting something like a fclose(fp) inside the ~this() is 
wrong, you need to add a specific method to that File class to ask for the 
closing of the file, because you generally can't rely on the GC for this, 
because a GC is free to even never collect objects, if there is enough RAM.

In my opinion it's correct to put something like a fclose(fp) inside the 
~this() only if you are sure this struct/class will be always allocated on the 
stack, so its destructor will always be called deterministically when the scope 
ends (a reference counting strategy too seems acceptable, because it is 
deterministic).

In a GC-based language you can't assume your destructors are run, so your 
destructors usually need to be empty, and you need to add other methods to free 
explicitly and manually (or with a scope(exit)) all the resources that aren't 
RAM.

Please take this cum grano salis, I am not an expert on this.

Bye,
bearophile

Reply via email to