On Friday, December 22, 2017 01:23:26 Mike Parker via Digitalmars-d-learn wrote: > The class destructor is not run during the lifetime of the > program. The fact that it's run during runtime termination is an > implementation detail. Another implementation might not run a > finalization at termination. > > So the destructors (finalizers) are only run when an object is > collected. No collection, no destructor call.
IIRC, there were reasons why running the destructors/finalizers when unloading dynamically loaded libraries was a problem too and one that we were stuck with, but I could be remembering incorrectly. Regardless, even if it were the case that it were guaranteed that all finalizers were run when the program exited, it would still be terrible practice to rely on it. It's trivial to end up in a situation where no collection is run for quite some time (e.g. just don't do much memory allocation for a while), which would leave any resources that needed to be freed by a finalizer unfreed for quite a while even though they weren't needed anymore. So practically speaking, it doesn't really matter where the finalizers are guaranteed to run. Relying on them to be run rather than forcing them to be run via destroy or using some other helper function is just going to cause problems, so it's just plain bad practice to rely on finalizers to be run to release resources. That's just life with GC's in general, not just D's. It's why C# has the while dispose/IDisposable thing, and why D code should either be using destroy to deal with freeing resources for a class or using structs on the stack for resources that need to be freed. Or alternate memory strategies can be used via std.experimental.allocator. The GC works great for lots of stuff but not for system resources. Honestly, in some ways, we'd be better off if D didn't even have finalizers. - Jonathan M Davis