Hi there,

this is the strangest thing I've ever encountered so far with XS. To me
it looks like a very obscure bug in perl, but hopefully it's not. The
Perl examples actually use autobox, but the very same behaviour shows up
when using a pure functional interface:

I have a very basic C function that triggers a Perl callback:

    SV * call_Pslice (const char *func) {
        SV *res;

        dSP;
        ENTER;
        SAVETMPS;
        PUTBACK;

        (void)call_pv(func, G_SCALAR);
        SPAGAIN;

        res = newSVsv(POPs);

        PUTBACK;
        FREETMPS;
        LEAVE;

        return sv_2mortal(res);
    }

Which is called from this XSUB (irrelevant parts snipped):

    void
    sliceI (string, ...)
            SV *string;
        PREINIT:
            ...
            ...
        PPCODE:
            if (items == 1)
                croak("Usage: $string->slice($n1, $n2, ...) OR ...");
                
            if (SvROK(ST(1)) || SvTYPE(ST(1)) == SVt_PV) {
                XPUSHs(call_Pslice("String::Ruby::pslice_dest"));
                XSRETURN(1);
            }

String::Ruby::pslice_dest() is likewise rather basic:

sub pslice_dest {
    my ($string, $pat) = @_;
    $pat = qr/\Q$pat/ if ref($pat) ne 'Regexp';
    $_[0] =~ s/$pat// and return substr $string, $-[0], $+[0] - $-[0];
}

It seems to be important that pslice_dest modifies $_[0] in-place (see
later). So now watch what happens:

    $s = "foobar";
    print $s->sliceI("foo"), "\n";
    print "$s\n";
    
    $t = "foobar";
    print $t->sliceI(qr/f.o/), "\n";
    print "$t\n";
    __END__
    foo
    bar
    bar

As you see, the return value of the second invocation of sliceI()
vanished. But not completely...now it's the point where it gets crazy:

    $s = "foobar";
    print $s->sliceI("foo"), "\n";
    print "$s\n";

    $t = "foobar";
    print +($a = $t->sliceI(qr/f.o/)), "\n";
    print "$a$t\n";
    foo
    bar
    foo
    bar
    
So

    print +($a = $t->sliceI(qr/f.o/)), "\n";

produces nothing (and it DOES NOT produce a use-of-unitialized-value
warning either with warnings enabled) but then

    print $a;

shows that the right value has been assigned? What is this?

So essentially, the return value (when calling sliceI for the second
time) is invisible...but when I assign it to a variable and later print
it, it's there. I tried to examine SP, it's all there. When I do
XSRETURN(1), the correct value is in TOPs. In short: I have every
indication that all is ok, only that the behaviour of my code speaks
otherwise.

There is a sister-function slice() that produces the same return value
as sliceI(), but does not change the first argument in place. slice()
behaves as expected, so there is also this strange interrelationship
with modifying $_[0] that seems to have some relevance.

Can someone confirm that this is a bug or else (and ideally:-) point me
to an error on my side? I am very puzzled.

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

Reply via email to