Hello everyone,

I was writing some unit tests and I also wanted to test that in certain cases object references are properly removed everywhere so that GC can collect them in order to make sure there is no memory leak. While trying to achieve this I learned that objects are not always collected at the time I would expect them to, so I documented current behavior and some tips.


/**
 * Compiled with:
 *   DMD32 D Compiler v2.060
 *   Copyright (c) 1999-2012 by Digital Mars written by Walter Bright
 *   Documentation: http://www.dlang.org/index.html
 */

module program;

import std.stdio;
import std.string;
import core.memory;

void main () {

  writeln("// ---------- beginning of main");

  mixin(writeAndExec(4, q{

    GC.collect();
    new a("a1");
    // GC will collect a1
    GC.collect();

    auto a2 = new a("a2");
    // GC will collect a2 because a2 will not be used in the future
    GC.collect();

    auto a3 = new a("a3");
    // GC will not collect a3 because a3 will be used in the future
    // tip: make some interaction with the object if you don't want
    // it to get collected before the end of scope GC.collect();
    GC.collect();
    a3.i = 1;

    {
      auto a4 = new a("a4");
      // GC will collect a4 because a4 will not be used in the future
      GC.collect();
    }

    {
      auto a5 = new a("a5");
      a5.i = 1;
      // maybe GC could collect a5 because a5 will be used
      // in the future, but it has been used and for some
      // (probably implementation) reasons GC does not collect it
      GC.collect();
    }

    ({
      auto a6 = new a("a6");
      a6.i = 1;
      // same as previous GC.collect (for a5)
      GC.collect();
    })();

    // maybe GC could collect a5 because a5 has gone out of scope
    // but for some (probably implementation) reasons GC does not
    // collect it, however, it will collect a6 that was declared
    // and used in a function call
    // tip: use function call (like a6 case) for a scope if you
    // want GC.collect(); to collect objects declared inside it
    GC.collect();

  }));

  writeln("// ---------- end of main");

}

class a {

  string id;
  int i;

  this (string id) {
    this.id = id;
    writeln("// ! ", this.id, " is now constructed");
  }

  ~this () {
    writeln("// ! ", this.id, " is now destructed");
  }

}

string writeAndExec (uint ident, string code) {
  string result = "";
  foreach (line; code.splitLines())
result ~= "writeln(`" ~ line[line.length > ident ? ident : 0 .. $] ~ "`);\n" ~ line ~ "\n";
  return result;
}


Reply via email to