View mode: basic / threaded / horizontal-split · Log in · Help
August 06, 2012
Missing destructor call using clear and base interface ref.
See the following code:

interface A{
}

class B : A{
    this(string name){this.name = name;}
    ~this(){
        writefln("Destructor %s", name);
    }
    string name;
}

void main(){
    B b0 = new B("b0");
    B b1 = new B("b1");

    A a = b0;
    clear(a);

    clear(b1);
}

Output:
Destructor b1

dmd 2.059

Why is the B destructor not invoked in the first clear?

Expected output:
Destructor b0
Destructor b1
August 06, 2012
Re: Missing destructor call using clear and base interface ref.
On 08/06/2012 06:59 AM, Roberto Delfiore wrote:
> See the following code:
>
> interface A{
> }
>
> class B : A{
> this(string name){this.name = name;}
> ~this(){
> writefln("Destructor %s", name);
> }
> string name;
> }
>
> void main(){
> B b0 = new B("b0");
> B b1 = new B("b1");
>
> A a = b0;
> clear(a);
>
> clear(b1);
> }
>
> Output:
> Destructor b1
>
> dmd 2.059
>
> Why is the B destructor not invoked in the first clear?
>
> Expected output:
> Destructor b0
> Destructor b1
>

Interesting.

I've tested the code with 2.060 after replacing 'clear' with 'destroy' 
(not required here, but because clear will be deprecated):

import std.stdio;

interface A{
}

class B : A{
    this(string name){this.name = name;}
    ~this(){
        writefln("Destructor %s", name);
    }
    string name;
}

void main(){
    B b0 = new B("b0");
    B b1 = new B("b1");

    A a = b0;
    writeln("Before clear(a)");
    destroy(a);

    writeln("Before clear(b1)");
    destroy(b1);

    writeln("Leaving main");
}

I see both of the destructor calls but the first one is executed out of 
order:

Before clear(a)
Before clear(b1)
Destructor b1
Leaving main
Destructor b0    <-- Here

Making 'a' a B produces the expected output:

    B a = b0;

Before clear(a)
Destructor b0    <-- Now at expected time
Before clear(b1)
Destructor b1
Leaving main

I guess destroy() is a no-op on an interface because your not seeing the 
destructor's effect and my seeing it can be explained by the 
non-deterministic behavior of the GC regarding destructor calls: If it 
is up to the GC, the destructor calls are not guaranteed.

Do others know? Shouldn't destroy() work on an interface?

Ali
August 09, 2012
Re: Missing destructor call using clear and base interface ref.
Thank you for your analysis, it's a very strange behavior. I
still can not figure out if there is something I don't know or if
it's is simply a bug.

Good answer: Shouldn't destroy() work on an interface?

On Monday, 6 August 2012 at 20:46:45 UTC, Ali Çehreli wrote:
> On 08/06/2012 06:59 AM, Roberto Delfiore wrote:
> > See the following code:
> >
> > interface A{
> > }
> >
> > class B : A{
> > this(string name){this.name = name;}
> > ~this(){
> > writefln("Destructor %s", name);
> > }
> > string name;
> > }
> >
> > void main(){
> > B b0 = new B("b0");
> > B b1 = new B("b1");
> >
> > A a = b0;
> > clear(a);
> >
> > clear(b1);
> > }
> >
> > Output:
> > Destructor b1
> >
> > dmd 2.059
> >
> > Why is the B destructor not invoked in the first clear?
> >
> > Expected output:
> > Destructor b0
> > Destructor b1
> >
>
> Interesting.
>
> I've tested the code with 2.060 after replacing 'clear' with 
> 'destroy' (not required here, but because clear will be 
> deprecated):
>
> import std.stdio;
>
> interface A{
> }
>
> class B : A{
>     this(string name){this.name = name;}
>     ~this(){
>         writefln("Destructor %s", name);
>     }
>     string name;
> }
>
> void main(){
>     B b0 = new B("b0");
>     B b1 = new B("b1");
>
>     A a = b0;
>     writeln("Before clear(a)");
>     destroy(a);
>
>     writeln("Before clear(b1)");
>     destroy(b1);
>
>     writeln("Leaving main");
> }
>
> I see both of the destructor calls but the first one is 
> executed out of order:
>
> Before clear(a)
> Before clear(b1)
> Destructor b1
> Leaving main
> Destructor b0    <-- Here
>
> Making 'a' a B produces the expected output:
>
>     B a = b0;
>
> Before clear(a)
> Destructor b0    <-- Now at expected time
> Before clear(b1)
> Destructor b1
> Leaving main
>
> I guess destroy() is a no-op on an interface because your not 
> seeing the destructor's effect and my seeing it can be 
> explained by the non-deterministic behavior of the GC regarding 
> destructor calls: If it is up to the GC, the destructor calls 
> are not guaranteed.
>
> Do others know? Shouldn't destroy() work on an interface?
>
> Ali
August 09, 2012
Re: Missing destructor call using clear and base interface ref.
09.08.2012 12:36, Roberto Delfiore пишет:
> Thank you for your analysis, it's a very strange behavior. I
> still can not figure out if there is something I don't know or if
> it's is simply a bug.
>
> Good answer: Shouldn't destroy() work on an interface?
>

Filled an issue:
http://d.puremagic.com/issues/show_bug.cgi?id=8527

-- 
Денис В. Шеломовский
Denis V. Shelomovskij
Top | Discussion index | About this forum | D home