Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

When aliasing sub arguments to @_ elements, PADTMP, READONLY flags are copied inconsistently

by vr (Curate)
on Jan 17, 2020 at 23:38 UTC ( [id://11111560]=perlquestion: print w/replies, xml ) Need Help??

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

I wrote a fragment of code dealing with passing pointers to pointers to data for some FFI calls. Reducing it now to SSCC(?)E: if written as

pack 'P', pack 'P', $data

then Perl warns "Attempt to pack pointer to temporary value", so it's easy to debug. But in my case, it was something like:

sub foo { pack 'P', $_[0] } foo pack 'P', $data;

-- no warnings, correct result for single call, but incorrect if return values are not used immediately but e.g. stored. Then I ran some tests:

>perl -MDevel::Peek -we "Dump 1; sub foo{Dump $_[0];$_[0]=1} foo(1)" SV = IV(0x653478) at 0x653488 REFCNT = 1 FLAGS = (IOK,READONLY,PROTECT,pIOK) IV = 1 SV = IV(0x653358) at 0x653368 REFCNT = 1 FLAGS = (IOK,READONLY,PROTECT,pIOK) IV = 1 Modification of a read-only value attempted at -e line 1. >perl -MDevel::Peek -we "Dump 1+1; sub foo{Dump $_[0];$_[0]=1} foo(1+1 +)" SV = IV(0x2612cf8) at 0x2612d08 REFCNT = 1 FLAGS = (PADTMP,IOK,READONLY,PROTECT,pIOK) IV = 2 SV = IV(0xfcb140) at 0xfcb150 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 2

Why is not PADTMP flag copied to $_[0], and why, if present, it also prevents copying READONLY?

  • Comment on When aliasing sub arguments to @_ elements, PADTMP, READONLY flags are copied inconsistently
  • Select or Download Code

Replies are listed 'Best First'.
Re: When aliasing sub arguments to @_ elements, PADTMP, READONLY flags are copied inconsistently
by ForgotPasswordAgain (Priest) on Jan 18, 2020 at 18:36 UTC

      I don't have an answer either, but following the RT link in that post leads to an issue that was closed in 2013: https://github.com/Perl/perl5/issues/6453. However, I can reproduce the behaviour on Strawberry perl 5.30.

Re: When aliasing sub arguments to @_ elements, PADTMP, READONLY flags are copied inconsistently
by ikegami (Patriarch) on Jan 20, 2020 at 16:16 UTC

    $_[0] is not a copy. It's literally the same scalar that was passed as an argument. That means the first 1+1 produced a read-only scalar and the second one didn't.

    We can see some differences in the generated code.

    $ perl -MO=Concise,-exec -MDevel::Peek -we'Dump 1; sub foo{Dump $_[0]; +$_[0]=1} foo(1)' 1 <0> enter 2 <;> nextstate(main 44 -e:1) v:{ 3 <$> const[IV 1] s 4 <2> Devel_Peek_Dump vK/1 5 <;> nextstate(main 46 -e:1) v:{ 6 <0> pushmark s 7 <$> const[IV 1] sM 8 <#> gv[IV \&main::foo] s 9 <1> entersub vKS a <@> leave[1 ref] vKP/REFC -e syntax OK
    $ perl -MO=Concise,-exec -MDevel::Peek -we'Dump 1+1; sub foo{Dump $_[0 +];$_[0]=1} foo(1+1)' 1 <0> enter 2 <;> nextstate(main 44 -e:1) v:{ 3 <$> const[IV 2] s/FOLD 4 <2> Devel_Peek_Dump vK/1 5 <;> nextstate(main 46 -e:1) v:{ 6 <0> pushmark s 7 <$> const[IV 2] sM/FOLD 8 <#> gv[IV \&main::foo] s 9 <1> entersub vKS a <@> leave[1 ref] vKP/REFC -e syntax OK

    So it appears that a folded constant (FOLD) in lvalue context (M) returns a writable scalar.

    We can also see the difference when using the referencing operator or foreach, as they also also impose an lvalue context.

    $ perl -MDevel::Peek -e'Dump(${\1})' SV = IV(0x8549e4010) at 0x8549e4020 REFCNT = 1 FLAGS = (IOK,READONLY,PROTECT,pIOK) IV = 1 $ perl -MDevel::Peek -e'Dump(${\(1+1)})' SV = IV(0x7ed5d4d610) at 0x7ed5d4d620 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 2 $ perl -MDevel::Peek -e'Dump($_) for 1' SV = IV(0x151c4b8240) at 0x151c4b8250 REFCNT = 2 FLAGS = (IOK,READONLY,PROTECT,pIOK) IV = 1 $ perl -MDevel::Peek -e'Dump($_) for 1+1' SV = IV(0x567114cd90) at 0x567114cda0 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 2

    I believe this is intentional. Addition normally produces a writable scalar, and those semantics are being preserved even when the operands of the addition are constants.

      Thank you all for useful links and answers, I should have done better research to at least find ref to read-only alias ... why?, which itself links far further into the past. Still not sure how to justify why with foo(1+1) the $_[0] is OK to be writeable, but with foo(1) it should die. Following previous discussion, the impression now is that it's either not a bug but vague (because of dynamic language(?)) area, or bug of very low priority, fixing of which can break/slower existing code (?).

      As to from where I started (foo(pack 'P', $data)), with hindsight, of course $_[0] is "pointable" for as long as staying within a sub, and returning that pointer to outside is entirely programmer's (my) fault, Perl couldn't help :(

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11111560]
Approved by GrandFather
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2024-04-20 00:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found