www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - lifetime of dynamically allocated memory

reply dave <garapata gmail.com> writes:
I'm trying to figure out if a dynamically allocated memory in D is getting
collected with this simple test (using tango):

class Foo {
    ~this() {
        // destructor
    }
}

struct Item {
    Foo a;
}

Item[] items;
items.length = 1;
items[0] = Item();
items[0].a = new Foo();

items = null;

GC.collect();

I assume that calling GC.collect(); forces gc to go through and free up memory
for any unreferenced objects. It seems that the destructor for Foo isn't being
called. I'm not sure if the reference is still used somewhere or do I have to
explicitly call 'delete items[0].a' to ensure that the memory is freed?
May 31 2010
next sibling parent reply torhu <no spam.invalid> writes:
On 31.05.2010 22:27, dave wrote:
 I'm trying to figure out if a dynamically allocated memory in D is getting
 collected with this simple test (using tango):

 class Foo {
      ~this() {
          // destructor
      }
 }

 struct Item {
      Foo a;
 }

 Item[] items;
 items.length = 1;
 items[0] = Item();
 items[0].a = new Foo();

 items = null;

 GC.collect();

 I assume that calling GC.collect(); forces gc to go through and free up memory
 for any unreferenced objects. It seems that the destructor for Foo isn't being
 called. I'm not sure if the reference is still used somewhere or do I have to
 explicitly call 'delete items[0].a' to ensure that the memory is freed?

I'm not sure why it doesn't work. But it's always better to post the code you're actually using, since now we can't be sure that you're not doing something else then what you think you're doing. If you know what I mean. :)
May 31 2010
parent dave <garapata gmail.com> writes:
== Quote from torhu (no spam.invalid)'s article
 On 31.05.2010 22:27, dave wrote:
 I'm trying to figure out if a dynamically allocated memory in D is getting
 collected with this simple test (using tango):

 class Foo {
      ~this() {
          // destructor
      }
 }

 struct Item {
      Foo a;
 }

 Item[] items;
 items.length = 1;
 items[0] = Item();
 items[0].a = new Foo();

 items = null;

 GC.collect();

 I assume that calling GC.collect(); forces gc to go through and free up memory
 for any unreferenced objects. It seems that the destructor for Foo isn't being
 called. I'm not sure if the reference is still used somewhere or do I have to
 explicitly call 'delete items[0].a' to ensure that the memory is freed?

code you're actually using, since now we can't be sure that you're not doing something else then what you think you're doing. If you know what I mean. :)

I was trying it out on a clean slate...then I realized it works as intended, see attach file. Then I was trying to figure out why it didn't work when I was testing it before and realized that I defined both the class and the struct within the scope of the function (attachment 2). Seems kinda weird that it wouldn't work that way...
May 31 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 31 May 2010 16:27:20 -0400, dave <garapata gmail.com> wrote:

 I'm trying to figure out if a dynamically allocated memory in D is  
 getting
 collected with this simple test (using tango):

 class Foo {
     ~this() {
         // destructor
     }
 }

 struct Item {
     Foo a;
 }

 Item[] items;
 items.length = 1;
 items[0] = Item();
 items[0].a = new Foo();

 items = null;

 GC.collect();

 I assume that calling GC.collect(); forces gc to go through and free up  
 memory
 for any unreferenced objects. It seems that the destructor for Foo isn't  
 being
 called. I'm not sure if the reference is still used somewhere or do I  
 have to
 explicitly call 'delete items[0].a' to ensure that the memory is freed?

It looks like you found that this code sample works, but I'd warn against trying to "prove" the GC in this way. The scanner scans the stack and registers from each thread. The registers make it very difficult to prove things, because you don't know what's in the registers by looking at the code. So even if you have no references to objects when you call GC.collect, there may be stale registers that point to those objects. And in response to your query, explicitly calling delete will ensure deleting of memory, but in general, you should let the GC do its job. And for some more advice -- don't define destructors unless you have resources that are not managed by the GC (such as an open file). The GC does not guarantee order of destruction, so any GC-managed references in the object being destructed are undefined. -Steve
Jun 01 2010