Thread overview
scope attribute and catching exception
Oct 13, 2008
Paolo Invernizzi
Oct 13, 2008
Denis Koroskin
Oct 13, 2008
Paolo Invernizzi
Oct 13, 2008
Max Samukha
Oct 13, 2008
Paolo Invernizzi
Oct 13, 2008
Max Samukha
October 13, 2008
Hi all,
Someone can explain me why the scope attribute of r2 is not satisfied? It's a bug or an expected behaviour?

Paolo

module tests.d.scopes.t02.test;

class Resource {
    static int allocated = 0;
    this( bool mustThrow = false ){
        allocated ++;
        if( mustThrow ) throw new Exception("bang");
    }
    ~this(){
        allocated --;
    }
}

void main(){


    // Why the destructor of r2 is not called when exiting the scope?
    {
        try {
            scope r1 = new Resource();
            scope r2 = new Resource(true);
        }
        catch(Exception e){}
    }
    //assert( Resource.allocated == 0); // Expected
    assert( Resource.allocated == 1 ); // What's happening

}
October 13, 2008
On Mon, 13 Oct 2008 13:50:46 +0400, Paolo Invernizzi <arathorn@fastwebnet.it> wrote:

> Hi all,
> Someone can explain me why the scope attribute of r2 is not satisfied? It's a bug or an expected behaviour?
>
> Paolo
>
> module tests.d.scopes.t02.test;
>
> class Resource {
>     static int allocated = 0;
>     this( bool mustThrow = false ){
>         allocated ++;
>         if( mustThrow ) throw new Exception("bang");
>     }
>     ~this(){
>         allocated --;
>     }
> }
>
> void main(){
>    // Why the destructor of r2 is not called when exiting the scope?
>     {
>         try {
>             scope r1 = new Resource();
>             scope r2 = new Resource(true);
>         }
>         catch(Exception e){}
>     }
>     //assert( Resource.allocated == 0); // Expected
>     assert( Resource.allocated == 1 ); // What's happening
> }

Looks like no destructor is called if ctor throws an exception.
Try throwing outside of it and see what happens.
October 13, 2008
On Mon, 13 Oct 2008 05:50:46 -0400, Paolo Invernizzi <arathorn@fastwebnet.it> wrote:

>Hi all,
>Someone can explain me why the scope attribute of r2 is not satisfied? It's a bug or an expected behaviour?
>
>Paolo
>
>module tests.d.scopes.t02.test;
>
>class Resource {
>    static int allocated = 0;
>    this( bool mustThrow = false ){
>        allocated ++;
>        if( mustThrow ) throw new Exception("bang");
>    }
>    ~this(){
>        allocated --;
>    }
>}
>
>void main(){
> 
> 
>    // Why the destructor of r2 is not called when exiting the scope?
>    {
>        try {
>            scope r1 = new Resource();
>            scope r2 = new Resource(true);
>        }
>        catch(Exception e){}
>    }
>    //assert( Resource.allocated == 0); // Expected
>    assert( Resource.allocated == 1 ); // What's happening
> 
>}

because r2 wasn't successfully created and there is nothing to call the destructor on:

class Resource {
    static int allocated = 0;
    this( bool mustThrow = false )
   {
        scope(success)
            allocated++;
        if( mustThrow ) throw new Exception("bang");
    }
    ~this(){
        allocated --;
    }
}

October 13, 2008
Denis Koroskin Wrote:

> Looks like no destructor is called if ctor throws an exception. Try throwing outside of it and see what happens.

In that case everything is ok. So it's a bug?

    // In this case everything it's ok
    {
        try {
            scope r1 = new Resource();
            scope r2 = new Resource();
            throw new Exception("bang");
        }
        catch(Exception e){}
    }
    assert( Resource.allocated == 0); // Expected


October 13, 2008
Max Samukha Wrote:

> because r2 wasn't successfully created and there is nothing to call the destructor on:

I think is more complicated... see this:

module tests.d.scopes.t02.test;

class Resource {
    static int allocated = 0;
    this( bool mustThrow = false ){
        allocated ++;
        if( mustThrow ) throw new Exception("bang");
    }
    ~this(){
        allocated --;
    }
}
class Factory {
    Resource resource(bool b=false){
        return new Resource(b);
    }
}

import std.gc, std.stdio;
void main(){
    // In this case everything it's ok
    {
        try {
            scope r1 = new Resource(true);
            assert( false );
        }
        catch(Exception e){}
        assert( Resource.allocated == 1);
        std.gc.fullCollect();
        assert( Resource.allocated == 1 );
    }

    Resource.allocated = 0;

    // In this case the destructor IS called, only on collect...
    {
        auto f = new Factory();
        try {
            scope r1 = f.resource(true);
            assert( false );
        }
        catch(Exception e){}
        assert( Resource.allocated == 1);
        std.gc.fullCollect();
        assert( Resource.allocated == 0 ); // Dho! Destructor called!
    }
}


October 13, 2008
On Mon, 13 Oct 2008 08:03:32 -0400, Paolo Invernizzi <arathorn@fastwebnet.it> wrote:

>Max Samukha Wrote:
>
>> because r2 wasn't successfully created and there is nothing to call the destructor on:
>
>I think is more complicated... see this:
>
>module tests.d.scopes.t02.test;
>
>class Resource {
>    static int allocated = 0;
>    this( bool mustThrow = false ){
>        allocated ++;
>        if( mustThrow ) throw new Exception("bang");
>    }
>    ~this(){
>        allocated --;
>    }
>}
>class Factory {
>    Resource resource(bool b=false){
>        return new Resource(b);
>    }
>}
>
>import std.gc, std.stdio;
>void main(){
>    // In this case everything it's ok
>    {
>        try {
>            scope r1 = new Resource(true);
>            assert( false );
>        }
>        catch(Exception e){}
>        assert( Resource.allocated == 1);
>        std.gc.fullCollect();
>        assert( Resource.allocated == 1 );
>    }
> 
>    Resource.allocated = 0;
> 
>    // In this case the destructor IS called, only on collect...
>    {
>        auto f = new Factory();
>        try {
>            scope r1 = f.resource(true);
>            assert( false );
>        }
>        catch(Exception e){}
>        assert( Resource.allocated == 1);
>        std.gc.fullCollect();
>        assert( Resource.allocated == 0 ); // Dho! Destructor called!
>    }
>}
>

I think this is a bug.