www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - problem with delegates and arrays?

reply Sean Kelly <sean f4.ca> writes:
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:

0, 8:

So as far as I can tell, the stack pointer is messed up for dynamic arrays
within delegates.
Jun 17 2004
parent reply Charlie <Charlie_member pathlink.com> writes:
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:

0, 8:

So as far as I can tell, the stack pointer is messed up for dynamic arrays
within delegates.
Jun 17 2004
parent reply Sean Kelly <sean f4.ca> writes:
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.
Jun 17 2004
parent reply Sean Kelly <sean f4.ca> writes:
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.
Jun 17 2004
parent "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
"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; }
Jun 17 2004