Thread overview
ref return function using foreach ref result segfaults. Compiler bug?
Nov 13, 2012
Rob T
Nov 13, 2012
Kenji Hara
Nov 13, 2012
Rob T
November 13, 2012
Hard to describe this problem, see code and read comments below.

class A
{
   private int _v;
	
   this( int a_v )
   {
      _v = a_v;
   }

   @property size_t length()
   {
   	return 1;
   }
   int opApply( int delegate( ref int a_v ) a_dg )
   {
      int result = 0;
      for ( ulong i = 0; i < length; ++i )
      {
         result = a_dg( this.opIndex( i ) );
         if ( result ) break;
      }
      return result;
   }
   ref int opIndex( size_t a_iPos )
   {
      return _v;
   }

}

class B : A
{
   this( int a_v )
   {
      super(a_v);
   }

   ref int find( int a_What )
   {
      foreach( val; super )
      {
         if ( val == a_What )
            return val;
      }
      throw new Exception("value not found");
   }
}

main()
{
    auto v_B = new B(500);
    writefln("Search = %d", v_B.find(500) );
    return 0;
}


When the return value of find() is ref, it segfaults or returns garbage. If the return value is a copy it works OK.

The only oddity I can see is that 'val' goes out of scope, but it's a ref return value (pointer) to _v (right?), so it should work anyway.

This looks like a bug in the compiler to me.

What do you guys think?

--rt

November 13, 2012
On Tuesday, 13 November 2012 at 08:50:16 UTC, Rob T wrote:
> Hard to describe this problem, see code and read comments below.
>
> class A
> {
>    private int _v;
> 	
>    this( int a_v )
>    {
>       _v = a_v;
>    }
>
>    @property size_t length()
>    {
>    	return 1;
>    }
>    int opApply( int delegate( ref int a_v ) a_dg )
>    {
>       int result = 0;
>       for ( ulong i = 0; i < length; ++i )
>       {
>          result = a_dg( this.opIndex( i ) );
>          if ( result ) break;
>       }
>       return result;
>    }
>    ref int opIndex( size_t a_iPos )
>    {
>       return _v;
>    }
>
> }
>
> class B : A
> {
>    this( int a_v )
>    {
>       super(a_v);
>    }
>
>    ref int find( int a_What )
>    {
>       foreach( val; super )
>       {
>          if ( val == a_What )
>             return val;
>       }
>       throw new Exception("value not found");
>    }
> }
>
> main()
> {
>     auto v_B = new B(500);
>     writefln("Search = %d", v_B.find(500) );
>     return 0;
> }
>
>
> When the return value of find() is ref, it segfaults or returns garbage. If the return value is a copy it works OK.
>
> The only oddity I can see is that 'val' goes out of scope, but it's a ref return value (pointer) to _v (right?), so it should work anyway.
>
> This looks like a bug in the compiler to me.
>
> What do you guys think?

This issue looks like bug8093.
http://d.puremagic.com/issues/show_bug.cgi?id=8093

And the code works correctly in git head (dmd2.061alpha). Therefore, I think that the bug is fixed very recently.

Kenji Hara
November 13, 2012
On Tuesday, 13 November 2012 at 12:31:26 UTC, Kenji Hara wrote:
>
> This issue looks like bug8093.
> http://d.puremagic.com/issues/show_bug.cgi?id=8093
>
> And the code works correctly in git head (dmd2.061alpha). Therefore, I think that the bug is fixed very recently.
>
> Kenji Hara

Thanks for the response Kenji! I'll implement a work-a-round for now and won't bother filing a bug report.

--rt