As it happens, Nim's GC is not "unprofessional" compared to others, but it's 
understandable how that could be falsely assumed.......... :D

Basically, the thing that is apparently the confusing factor is that Nim has a 
**conservative garbage collector**. This means that the [mark and sweep 
mechanism of the] GC works by _scanning the stack_ for `ref` s. Thus, if the 
stack contains a value that looks like a `ref` (in terms of bit pattern), the 
object that `ref` points to is kept alive. This is how the GC can determine if 
something is garbage _in the first place_. So, if you call ` GC_FullCollect()` 
while a `ref` is still around, the object will not be deleted, and the 
finalizer will **not** be called. This is correct behavior, though. If the GC 
deleted objects that were still reachable, use-after-free would be inevitable. 
A conservative GC must keep all objects that have **at least one alias 
/ref/pointer/handle/whatever** alive, because code expects to still be able to 
use the pointed-to value.

The cost-benefit analysis between this system and non-conservative garbage 
collection is [not always 
clear-cut](http://www.hboehm.info/gc/conservative.html). For languages that use 
conventional compilers that are _not made for GCs_ (and not, say bytecode 
interpreters, like Java), conservative garbage collection is the only practical 
and useful solution to the memory management dilemma. Nim compiles to C and C 
doesn't understand GC (not like JS does, where its a **language builtin** ).

For programmers, having a nondeterministic GC means that you should not count 
on finalizers being called _deterministically_ (naturally). You could use them 
to clean up a resource that must be reclaimed _eventually_ , like memory, but 
for immediate reclamation of resources at the end of the scope, use `try` / 
`finally` with explicit deallocation/cleanup/whatever. This pattern of 
automatic memory management and manual resource management is quite widespread 
in GC'd languages. Java does the same thing. You must call `File.close()`. 
Sure, the runtime or your OS will close the file _eventually_ , but cleaning it 
up immediately is the responsibility of the programmer.

To solve this problem, it seems that @Araq is working on implementing 
destructors for Nim. These will clean up stack (and heap??) resources 
implicitly at the end of the scope.

Araq, a few questions:

  * With the new runtime: say there is a type `object Foo` with a destructor. 
**If I have a ``ref Foo``, will the ``ref`` version be cleaned up 
deterministically?** I heard somewhere that GC'd memory has/will have 
destructors called from finalizers, but we also have a rework of the Nim memory 
management model coming to use ownership semantics, as I understand.
  * After [another thread's](https://forum.nim-lang.org/t/4022#25037) 
discussion of `defer` found that it supposedly _does_ do what it's supposed to, 
what do you think now? Should Nim programmers be using `defer` to clean up 
resources until destructors are more well tested (There are still a few 
[issues](https://github.com/nim-lang/Nim/issues?q=is%3Aopen+is%3Aissue+label%3ADestructors)
 AFAIK)?


Reply via email to