Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Reverting the internals of an IV to their original states

by syphilis (Archbishop)
on Dec 27, 2021 at 04:19 UTC ( [id://11139925]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

As revealed in this demo by Devel::Peek::Dump(), calling foo($sv) can make significant alterations to the internals of $sv:
use strict; use warnings; use Devel::Peek; use Inline C =><<'EOC'; void foo(SV * sv) { printf("\n%s\n\n", SvPV_nolen(sv)); /* SvPOK_off(sv); SvPV_set(sv, NULL); */ } EOC my $sv = 12345; Dump $sv; foo($sv); Dump($sv); __END__ Outputs: SV = IV(0x4ecd70) at 0x4ecd80 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 12345 12345 SV = PVIV(0x4f0088) at 0x4ecd80 REFCNT = 1 FLAGS = (IOK,POK,pIOK,pPOK) IV = 12345 PV = 0x25a4448 "12345"\0 CUR = 5 LEN = 10
Inside that XS sub foo() is there a simple way that, having called SVPV_nolen(), the internals of the provided argument can be restored to the states they held just prior to the calling of foo($sv) ?

Inclusion of the commented-out C-code in foo() goes some way to doing that ... but not all the way.
It will change the second Dump() to:
SV = PVIV(0x4f0088) at 0x4ecd80 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 12345 PV = 0
That looks about right except that the SV is still PVIV, and the PV slot, although cleared, is still being displayed. Perhaps the PV slot is being displayed simply because the SV is PVIV, and the solution lies in getting the "PVIV" to revert to "IV".

Cheers,
Rob

Replies are listed 'Best First'.
Re: Reverting the internals of an IV to their original states
by dave_the_m (Monsignor) on Dec 27, 2021 at 10:31 UTC
    In general, perl doesn't have APIs to downgrade SVs. If you're really bothered, make a temporary copy of the value, print using that, then free it. By the way, your code with the SvPV_set() will leak the string buffer each time.

    Dave.

      If you're really bothered, make a temporary copy of the value, print using that, then free it

      Yes, that's pretty much my goto approach when I have a sub that can potentially alter the flags of its arguments && I want to avoid doing so.
      In some cases it can be a bit tedious, and I've often wondered whether it's feasible to instead just allow the flag alteration(s) to occur and then revert it/them. (Hence my question.)

      For the demo case I provided, just calling SvPOK_off(sv); would be sufficient to restore the flags (as reported by Devel::Peek::Dump) to their original values. That would then have $sv Dump()ing to:
      SV = PVIV(0x33fea8) at 0x33d0e0 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 12345 PV = 0x2838458 "12345"\0 CUR = 5 LEN = 10
      If the objective is to simply keep those flags unchanged, then that objective has now been met. But are there any gotchas associated with leaving $sv in that state ?

      I'm not really all that bothered about flags being changed - except for when it happens without good reason.
      As an example of flags being changed for no good reason, consider:
      > perl -MStorable -MDevel::Peek -le "$v = 2**70; Dump($v); $f = Stora +ble::freeze(\$v); Dump($v)" SV = NV(0x47e370) at 0x47e388 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 1.18059162071741e+21 SV = PVNV(0x30a3e8) at 0x47e388 REFCNT = 1 FLAGS = (NOK,pIOK,pNOK,IsUV) UV = 18446744073709551615 NV = 1.18059162071741e+21 PV = 0
      I don't think we should assume that such an unannounced and unexpected alteration to the flags of $v would be of no consequence to the user.

      Cheers,
      Rob
        Well the entire philosophy of the perl core for the last 25 years has been that whenever you want to access the value of an SV, you request the perl core to update that SV into the form you want, then access the appropriate slot for the value (the string or IV or whatever). For the vast majority of use cases this "just works". It's only a few edge cases (like data serialisers and bitwise operators) where this becomes an issue. Note that perl will only set the *private* versions of the flags if the conversion isn't fully accurate / reversible, such as the pIOK but not IOK in your example above.

        This is very much tied to the perl language philosophy that values are type agnostic and the type of operation is specified by the operator, e.g. eq versus ==.

        Although those flag changes are "unannounced", it's the sort of thing that happens to most SVs in most perl programs. I think you'd have to give a practical example of real harm being caused by these flag changes.

        Dave.

Re: Reverting the internals of an IV to their original states
by ikegami (Patriarch) on Dec 27, 2021 at 17:49 UTC

    calling foo($sv) can make significant alterations to the internals of $sv

    More precisely, it's stringifying $sv that did this. "$sv" would have the save effect.

Re: Reverting the internals of an IV to their original states
by etj (Deacon) on Dec 27, 2021 at 07:14 UTC
    I have to ask: what are you trying to achieve? :-)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-04-25 10:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found