www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Weird behavior: array of RefCounted struct

reply "Xaqq" <kapp.arno gmail.com> writes:
Hello,

I'm very new to D. I started playing around trying to understand 
language behavior. How to use RAII in D, etc.

I'm having trouble understanding what is happening here, and 
maybe this is a bug.

Here is the code showing the weird behavior. I'm using dmd 2.066 
(on linux)

import std.stdio;
import std.typecons;
import std.traits;

struct Frame
{
   ~this(){
     printf("DTOR FRAME\n");
   }

   this(int v)  {
     writeln("CTOR FRAME");
     this.i = v;
   }
   int i;
}

class Container
{
   void add(int i){
     f ~= RefCounted!(Frame)(i);
   }

   ~this()  {
     printf("DTOR CONT\n");
     foreach (ref mbr; f) writeln("Count: ", 
mbr.refCountedStore.refCount);
     f = [];
   }

   this() {
     writeln("CTOR CONT");
   }

   RefCounted!(Frame)[] f;
}

void main()
{
   auto l = scoped!Container();
   foreach (i ; 1..10)
       l.add(i);
}

While the destructor of Container is called, the frame's 
destructor are not called. Printing the current reference count 
for each frame gives unexpected results.

Below is the program output:

CTOR CONT
CTOR FRAME
CTOR FRAME
CTOR FRAME
CTOR FRAME
CTOR FRAME
CTOR FRAME
CTOR FRAME
CTOR FRAME
CTOR FRAME
DTOR CONT
Count: 4
Count: 3
Count: 3
Count: 2
Count: 2
Count: 2
Count: 2
Count: 1
Count: 1

Am I doing something wrong or is this a bug? Could someone please 
try to explain?

Thanks !
Sep 09 2014
next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 09 Sep 2014 16:13:24 +0000
Xaqq via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 Am I doing something wrong or is this a bug? Could someone please=20
 try to explain?
ah, this is a very funny thing. you are using D dynamic array to keep refcounted objects and by appending element to this array you are hitting "array resizing". and from that moment everything goes wrong: compiler needs to copy old array elements to new resized array. and copying increases refcount. yet compiler doesn't know about this and doesn't call destructors for copied elements (so refcount not decreasing). this is perfectly ok for garbage-collected elements, but completely wrong for refcounted elements. to make a long story short: don't store RefCounted in dynamic arrays. this will not work as expected yet.
Sep 09 2014
prev sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 09 Sep 2014 16:13:24 +0000
Xaqq via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

or, to make even stronger requirement: do not mix GC and refcounting.
either do manual memory management and refcounting, or use GC. and
remember about "hidden" GC operations, such as dynamic array resizing.
Sep 09 2014