Garbage Collection, Allocators/Deallocators and

Ivo Kasiuk i.kasiuk at gmx.de
Sat Sep 18 09:08:03 PDT 2010


Am Samstag, den 18.09.2010, 10:08 -0400 schrieb Sean Kelly:
> Ivo Kasiuk Wrote:
> 
> > Hi,
> > 
> > to improve my understanding of the GC and when/how
> > allocators/deallocators and constructors/destructors get called, I wrote
> > a little test program. And now I understand even less than before...
> ...
> > Running this with DMD 2.049, I observed the following:
> > 
> > - S1(int), S2(int), C1(), C2(), S1.new and S2.new get invoked in every
> > cycle of the loop, as you would expect.
> > 
> > - ~C2() also gets invoked frequently.
> > 
> > - ~S1(), ~S2(), ~C1(), S1.delete and C1.delete never ever get called.
> > 
> > - The program does not run out of memory and actually has a relatively
> > modest memory footprint, so it does not seem to leak memory. (When using
> > std.c.stdlib.malloc instead of GC.malloc it runs out of memory almost
> > immediately).
> > 
> > It is good to see that the GC apparently really frees the unreferenced
> > memory again. However, I don't understand why the deallocators and the
> > destructors (apart from ~C2) do not get called. If the memory for the
> > objects gets freed, as is apparently the case, then why are there no
> > destructor and deallocator calls for these objects?
> 
> The deallocator is only called if you delete the object, not when it's finalized by the GC.  The GC will only finalize something that is in its memory space, so if this happens there's no need to call the deallocator.

Ok, that makes sense. So the deallocators really should not get called
in this case. But why are the destructors not invoked when the GC
finalizes the objects?

Exploring the example a bit further:
If C's malloc is used instead of GC.malloc then the deallocators also
are not called and the program runs out of memory. How are the objects
supposed to get finalized in this case - do I have to use the delete
keyword explicitly?

An interesting case is when using C's malloc for C1 and using the scope
attribute for c1:

class C1 {
  ubyte[1_000_000] buf;
  new(size_t size) {
    void* ptr = std.c.stdlib.malloc(size);
    if (ptr is null)
      throw new OutOfMemoryError(__FILE__, __LINE__);
    writefln("C1.new(%d) = %x", size, ptr);
   return ptr;
  }
  delete(void* ptr) {
    writefln("C1.delete %x", ptr);
    if (ptr) std.c.stdlib.free(ptr);
  }
  this() { writeln("C1()"); }
  ~this() { writeln("~C1()"); }
}
...
  scope C1 c1 = new C1;

In this case, ~C1 gets invoked but not C1.delete. Nevertheless, the
memory appears to get freed (normal memory consumption, no OutOfMemory).
How does this happen?




More information about the Digitalmars-d-learn mailing list