in reply to Re: 5.42: Does m// toss a string around?
in thread 5.42: Does m// toss a string around?

Ah, thanks. If I understand correctly, it was 5.42 which fixed the long-standing issue with "pack 'P',".

(I think the PV method constructs new string rather than returns numeric value. I'll use "pack 'P'," for the next example, for brevity of output over Devel::Peek::Dump; there's no 5.42 below)

Wild goose chase, then, being sidetracked with imagined issue with 5.42, but initially I investigated s///, not m//. I now suspect similar reasons, related to COW, can you explain please? The 5.18 re-uses string buffer when new length is either the same or less than original. The 5.20 and then 5.26 loose both abilities.

print "$^V\n"; my $x = '0123456789'; { my $s = "$x$x"; $s =~ s/(.)$/a/; printf "%x\n", unpack "Q", pack "P", $s; $s =~ s/(.)$/b/; printf "%x\n", unpack "Q", pack "P", $s; } { my $s = "$x$x"; $s =~ s/.$//; printf "%x\n", unpack "Q", pack "P", $s; $s =~ s/.$//; printf "%x\n", unpack "Q", pack "P", $s; } __END__ v5.18.4 29cdda8 29cdda8 29ce1e8 29ce1e8 v5.20.3 2b774f8 2b774f8 2b76b78 2b76f38 v5.26.3 2c9e118 2c9d7b8 2c9da88 2b4ae88

Replies are listed 'Best First'.
Re^3: 5.42: Does m// toss a string around?
by ikegami (Patriarch) on Jan 22, 2026 at 13:50 UTC

    I think the PV method constructs new string rather than returns numeric value

    No.

    SvPVX creates an object that provide information about a scalar ($_[0] aka $s), then uses that object's PV method to obtain the address of the string buffer of $s.

    I now suspect similar reasons, related to COW, can you explain please?

    COW was introduced in 5.20. Before 5.20, hacks which malfunctioned and/or a more expensive alternative had to be used.

      (OK, the PV method doesn't matter) I thought I got it (s/// implies matching; and $& and friends COW-share, in a way, original buffer; hence replacement operator (after 5.18) always re-allocates) but now I think the following example shows "match and manually replace" doesn't force re-allocation, then why s/// does?

      use Devel::Peek qw( Dump ); $Devel::Peek::pv_limit = $Devel::Peek::pv_limit = 10; $_ = "x" x 99; $_ .= "x"; # Force unsharing. Dump( $_ ); /(.+)/; Dump( $_ ); $_ = 'aaa'; Dump( $_ ); print "\n\n"; $_ = "x" x 99; $_ .= "x"; # Force unsharing. Dump( $_ ); s/(.+)/aaa/; Dump( $_ ); __END__ 5.042000 SV = PV(0x1e2951e23e0) at 0x1e29521d298 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x1e295228ad0 "xxxxxxxxxx"...\0 CUR = 100 LEN = 101 SV = PV(0x1e2951e23e0) at 0x1e29521d298 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x1e295228ad0 "xxxxxxxxxx"...\0 CUR = 100 LEN = 101 SV = PV(0x1e2951e23e0) at 0x1e29521d298 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x1e295228ad0 "aaa"\0 CUR = 3 LEN = 101 SV = PV(0x1e2951e23e0) at 0x1e29521d298 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x1e295228ad0 "xxxxxxxxxx"...\0 CUR = 100 LEN = 101 SV = PV(0x1e2951e23e0) at 0x1e29521d298 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x1e295215d60 "aaa"\0 CUR = 3 LEN = 16

        So there's really two questions here.


        The first is why wasn't COW used for matching half of the code.

        COW is normally used for the copy for $& and friends, but it wasn't used in this case because there's not enough space in the buffer.

        CUR = 100 LEN = 101

        I think two bytes are needed. One for the NUL, and one for the COW reference count. Replace $_ .= "x"; with chop;, and you get:

        SV = PV(0x5deca7958ee0) at 0x5deca7994d68 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x5deca7998850 "xxxxxxxxxx"...\0 CUR = 98 LEN = 101 SV = PV(0x5deca7958ee0) at 0x5deca7994d68 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x5deca7998850 "xxxxxxxxxx"...\0 CUR = 98 LEN = 101 COW_REFCNT = 1 SV = PV(0x5deca7958ee0) at 0x5deca7994d68 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x5deca797ad20 "aaa"\0 CUR = 3 LEN = 16 COW_REFCNT = 1

        The second question is why does the scalar get a new buffer for the substitution.

        I'm guessing the buffer of the scalar is stolen rather than copied for $& and friends, since the expectation is that it will change.

        That means the scalar always gets a new buffer.