kixix has asked for the wisdom of the Perl Monks concerning the following question:

This is a cross-post from this SO question - see that for more details

I am printing to an in-memory file, like so:
my $memory_file; my $fh; open ($fh, '>', \$memory_file); print $fh "abc"; if( $memory_file =~ m/^.*$/ ) { print "yes\n" } else { print "no\n" }

For me, on perl 5.14.1, the above prints 'no', which is not what I expect.

Interestingly replacing $ with \z causes it to work, though \Z does not.

Also interestingly, if I assign to a temporary variable before doing the pattern match (and do the match against that temporary variable), it works as expected.

Does anyone have an explanation for this odd behavior? Is this documented anywhere? Or is it a bug?

Update: I logged this as a bug via perlbug. Thanks everyone for the investigation.

Replies are listed 'Best First'.
Re: pattern match against in-memory file causes odd behavior
by wrog (Friar) on Dec 28, 2011 at 05:51 UTC
    according to the definition in perlre, \Z and $ should, under all flag settings, be matching everywhere that \z does, so the fact that one is getting matches with \z but not \Z or $, is at best, an undocumented violation of that contract.

    Trying this out in my 5.10.1 debugger on (Debian)Linux, I'm getting quite erratic behavior:

      DB<525> open $fh, '>', \$memory
      DB<526> print $fh 'abc';
      DB<527> x $memory =~ m/(.*)\Z/
      empty array
      DB<528> print $fh 'def';
      DB<529> x $memory =~ m/(.*)\Z/
    0  'abcdef'
      DB<530> print $fh 'ghi';
      DB<531> x $memory =~ m/(.*)\Z/
      empty array
      DB<532> print $fh 'jkl';
      DB<533> x $memory =~ m/(.*)\Z/
      empty array
      DB<534> print $fh 'mno';
      DB<535> x $memory =~ m/(.*)\Z/
    0  'abcdefghijklmno'
    
    which just smells of buggity-bug-bug-bug.

      It seems in some cases the trailing \0 of the PV is missing (according to Devel::Peek), and in those cases, the regex doesn't match:

      use Devel::Peek; open my $fh, '>', \my $memory_file; for (qw(abc def ghi jkl mno)) { print $fh $_; Dump $memory_file; if ( $memory_file =~ m/^(.*)$/ ) { print "==> matched: $1\n" } } __END__ SV = PV(0x75cce8) at 0x783f70 REFCNT = 2 FLAGS = (PADMY,POK,pPOK) PV = 0x7b2e10 "abc"\0 CUR = 3 LEN = 8 ==> matched: abc SV = PV(0x75cce8) at 0x783f70 REFCNT = 2 FLAGS = (PADMY,POK,pPOK) PV = 0x7b2e10 "abcdef"\0 CUR = 6 LEN = 8 ==> matched: abcdef SV = PV(0x75cce8) at 0x783f70 REFCNT = 2 FLAGS = (PADMY,POK,pPOK) PV = 0x7b2e10 "abcdefghi" <--- !! CUR = 9 LEN = 16 SV = PV(0x75cce8) at 0x783f70 REFCNT = 2 FLAGS = (PADMY,POK,pPOK) PV = 0x7b2e10 "abcdefghijkl"\0 CUR = 12 LEN = 16 ==> matched: abcdefghijkl SV = PV(0x75cce8) at 0x783f70 REFCNT = 2 FLAGS = (PADMY,POK,pPOK) PV = 0x7b2e10 "abcdefghijklmno"\0 CUR = 15 LEN = 16 ==> matched: abcdefghijklmno

      Update: some further testing (with minor modifications) shows that there are also cases, where it does match despite a missing trailing \0.   So yes, erratic, at best :)

Re: pattern match against in-memory file causes odd behavior
by juster (Friar) on Dec 28, 2011 at 02:20 UTC

    Your example also works as expected (prints "yes") for perl 5.14.1 brewed on Mac OS X. Maybe Devel::Peek's Dump function would show some abnormality with your scalar?

Re: pattern match against in-memory file causes odd behavior
by Eliya (Vicar) on Dec 28, 2011 at 00:56 UTC
    For me, on perl 5.14.1, the above prints 'no', ...

    Just for the record, for me it prints 'yes' with 5.14.1 (on Linux).

Re: pattern match against in-memory file causes odd behavior
by TJPride (Pilgrim) on Dec 28, 2011 at 01:03 UTC
    I get yes also with 5.8.6 on Mac OS X. What do you get if you print $memory_file?
Re: pattern match against in-memory file causes odd behavior
by choroba (Cardinal) on Dec 28, 2011 at 14:45 UTC
    The bug is present in 5.14.2, too.