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...
Here is the program:

------------------------------------
import core.memory;
import std.stdio;

struct S1 {
  ubyte[1_000_000] buf;
  new(size_t size) {
    void* ptr = GC.malloc(size);
    writefln("S1.new(%d) = %x", size, ptr);
    return ptr;
  }
  delete(void* ptr) {
    writefln("S1.delete %x", ptr);
    if (ptr) GC.free(ptr);
  }
  this(int x) { writefln("S1(%d)", x); }
  ~this() { writeln("~S1()"); }
}

struct S2 {
  ubyte[1_000_000] buf;
  this(int x) { writefln("S2(%d)", x); }
  ~this() { writeln("~S2()"); }
}

class C1 {
  ubyte[1_000_000] buf;
  new(size_t size) {
    void* ptr = GC.malloc(size);
    writefln("C1.new(%d) = %x", size, ptr);
   return ptr;
  }
  delete(void* ptr) {
    writefln("C1.delete %x", ptr);
    if (ptr) GC.free(ptr);
  }
  this() { writeln("C1()"); }
  ~this() { writeln("~C1()"); }
}

class C2 {
  ubyte[1_000_000] buf;
  this() { writeln("C2()"); }
  ~this() { writeln("~C2()"); }
}

void f() {
  for (int i=0; i<10_000; i++) {
    S1* s1 = new S1(i);
    S2* s2 = new S2(i);
    C1 c1 = new C1;
    C2 c2 = new C2;
  }
}

void main() {
  f();
  GC.collect();
}
-----------------------------------------

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?

Thanks
Ivo Kasiuk

Reply via email to