Thread overview
problem with delegates and arrays?
Jun 17, 2004
Sean Kelly
Jun 17, 2004
Charlie
Jun 17, 2004
Sean Kelly
Oops
Jun 18, 2004
Sean Kelly
Jun 18, 2004
Kris
June 17, 2004
This code:

void fn( out char[] buf )
{
void fn2()
{
printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
}
fn2();
printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
}
int main()
{
char[] buf;
printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
fn( buf );
return 0;
}

prints:

0, 8:
1244976, 8: Ç ↕
0, 8:

So as far as I can tell, the stack pointer is messed up for dynamic arrays within delegates.


June 17, 2004
I dont see any delgates in there ?  I see the nested function ..

This problem goes away when you remove the 'out' and replace with 'in', however 'inout' seems also to fail.

Assiging buf a value fails also.

compiled with -inline it works as expected, weird.

Charlie

In article <casd8k$18ac$1@digitaldaemon.com>, Sean Kelly says...
>
>This code:
>
>void fn( out char[] buf )
>{
>void fn2()
>{
>printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
>}
>fn2();
>printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
>}
>int main()
>{
>char[] buf;
>printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
>fn( buf );
>return 0;
>}
>
>prints:
>
>0, 8:
>1244976, 8: Ç &#8597;
>0, 8:
>
>So as far as I can tell, the stack pointer is messed up for dynamic arrays within delegates.
>
>


June 17, 2004
In article <casnln$1oe1$1@digitaldaemon.com>, Charlie says...
>
>I dont see any delgates in there ?  I see the nested function ..

That's what I meant.  I should really learn to not post until after I've had some coffee :)

>This problem goes away when you remove the 'out' and replace with 'in', however 'inout' seems also to fail.

Yup, I noticed this too, so perhaps the problem is with parameter specifiers. However I think there's a related bug that's affecting me too.  I'm still working on shrinking this repro, but this is the best I've done so far:

interface I
{
void fn( char[] buf );
}

template T()
{
template doFn( CharT )
{
void fn( CharT[] val )
{
size_t	len	= 0;
CharT	ch;

void append( CharT ch )
{
printf( "%i, %i: %.*s\n", val.length, val.size, val );
if( ++len > val.length )
val.length = len * 2;
val[len-1] = ch;
}
ch = '1';
append( ch );
ch = '2';
append( ch );
ch = '3';
append( ch );
ch = '4';
append( ch );

val.length = len;
return this;
}
}
mixin doFn!(char) doFnC;
alias doFnC.fn fn;
}

class C : I
{
mixin T;
}

int main()
{
char[] buf;
I i = new C();
i.fn( buf );
printf( "%i, %i: %.*s\n", buf.length, buf.size, buf );
return 0;
}

prints:

0, 8:
2, 8: 1
2, 8: 12
6, 8: 123
0, 8:

Basically, in this code I can't use the inner function "append" at all.  If I add the "out" qualifier then the dynarray is garbage and I get an access violation, and if I leave it out then the changes don't persist once I leave the function.  With the above code, if every call to "append" is replaced with the code inside "append" then everything works as expected.


June 18, 2004
I just realized that this second problem is intended behavior.  I had mistakenly thought that dynamic arrays would be governed by the same rules as classes, ie. that they are reference counted and are always implicitly passed as inout.  It looks like the out qualifier must be used in order to have changes to dynarrays persist.  So the only bug I see is the corrupt stack pointer when using inner classes.


June 18, 2004
"Sean Kelly" wrote ...
> I just realized that this second problem is intended behavior.  I had
mistakenly
> thought that dynamic arrays would be governed by the same rules as
classes, ie.
> that they are reference counted and are always implicitly passed as inout.
It
> looks like the out qualifier must be used in order to have changes to
dynarrays
> persist.  So the only bug I see is the corrupt stack pointer when using
inner
> classes.

A while back I ran into this one also, Sean. I forget the title of the bug-report, but the resultant code looks like this (note the char[] tmp for getting around funky nesting stack alignment issues; you can't directly assign the argument 'x' from within the nested function):

/*****************************************

  Extract a char array from the current read-position

*****************************************/

        IReader get (out char[] x)
        {
                char[]  tmp;
                int     size;

                // callback to assign the prescribed content
                int read (void[] content)
                {
                        tmp = cast(char[]) content;
                        if (! mapped)
                              tmp = tmp.dup;
                        return tmp.length;
                }

                // how many bytes in this array?
                get (size);
                buffer.preserve (size, &read);

                // set output argument and go home
                x = tmp;
                return this;
        }