Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

PV value

by vmani_2012 (Initiate)
on Jul 12, 2012 at 18:05 UTC ( #981463=perlquestion: print w/replies, xml ) Need Help??
vmani_2012 has asked for the wisdom of the Perl Monks concerning the following question:

I ran this simple perl code

use strict; use Devel::Peek; my $a; $a=4; $a eq "13"; $a++; Dump($a); print $a; Dump($a);

when i executed this code, I got the following output

SV = PVIV(0x1a7fd44) at 0x1a716f4 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 5 PV = 0x1a63164 "4"\0 CUR = 1 LEN = 12 SV = PVIV(0x1a7fd44) at 0x1a716f4 REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 5 PV = 0x1a63164 "5"\0 CUR = 1 LEN = 12 5

The question here is, Dump($a) before print statement is

PV = 0x1a63164 "4"\0

and after is

PV = 0x1a63164 "5"\0

why the string value (PV) got incremented, any reason?

Replies are listed 'Best First'.
Re: PV value
by bulk88 (Priest) on Jul 12, 2012 at 18:19 UTC
    Because in the first Dump() call, $a didn't have a string in it. No POK flag. A scalar with all its data/content flags off (PADMY has nothing to do with data in the scalar), is undefined and the IV/NV/PV values, if allocated, are allocated but uninitialized memory at that point. The SV type, here PVIV, indicates what is allocated, but not what is currently in use. An undefined SV can be a SVt_PVMG or SVt_PVLV (largest scalar possible, after LV, the SV is not a Perl language Scalar anymore and any attempts to use a SV bigger than SVt_PVLV as a Perl Scalar will result in "bizarre copy of" panics), yet have no magic or Lvalueness attached. An undefined SV can be SVt_NULL, which has almost nothing allocated except the SV struct. I hope youve read atleast the first 1/3rd of illguts. Devel::Peek will show allocated but uninitialized data sometimes as a diagnostic tool so you can figure out if there is a mistake in the flags and the data is actually valid and you forgot a SvIOK_only when creating a IV SV the long way (sv_setiv is the short way). I'm not sure if the advanced fields of magic and LVs are shown if the SV isn't flagged as magic or LV by Devel::Peek.
Re: PV value
by ig (Vicar) on Jul 12, 2012 at 21:06 UTC presents some of the details of how perl stores and keeps track of variables and their values. It is a bit more complex than the simple model presended in perldata and the commonly used terms "variable" and "value". There are several data structures used and linked to each other in the case of most variables. Depending on the history of the variable, there will be various bits of memory allocated and with more or less current values.

    You can follow the evolution of $a at each step in your program by adding a few more Dump calls:

    use strict; use Devel::Peek; my $a; Dump($a); $a=4; Dump($a); $a eq "13"; Dump($a); $a++; Dump($a); print $a; Dump($a);

    Which produces:

    C:\Users\ian>perl SV = NULL(0x0) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY) SV = IV(0x1d9ec18) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 4 SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 4 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4 SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 5 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4 SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 5 PV = 0x1dbdf84 "5"\0 CUR = 1 LEN = 4 5

    The first Dump produces:

    SV = NULL(0x0) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY)

    At this point, the variable is declared but no value has been assigned. There is a root data structure allocated: SV, but no memory allocated to store a value: the value is undef and a NULL pointer value in the SV structure is sufficient to record this.

    After assigning an integer value to the variable, Dump produces:

    SV = IV(0x1d9ec18) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 4

    Here an IV structure has been allocated and the assigned value, 4, has been stored in it. The pointer in the SV structure now points to the IV structure: it is not a NULL pointer any more. Flags are set to indicate that the variable now contains a valid integer value (IOK and pIOK).

    Next you do a string comparison, for which perl needs to convert the variable value to a string. After this Dump shows:

    SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 4 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4

    The string value could be created, used then discarded, but instead perl updates the stored value, keeping the string value in case it might be used again. The integer value is still correct, so the variable now has two values: an integer value and a string value. Two data structures are used: the original SV and a PVIV structure which contains the integer value and a pointer to the string value. And the flags are updated to indicate that there are valid integer and string values.

    Your next operation is to increment $a. This is an operation on its integer value. In this case, perl is frugal and does only enough work to record the result. The integer value is changed but the string value is not changed. Rather, the flags indicating a valid string value are turned off. After this, Dump produces:

    SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 5 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4

    Note that perl does not bother to change the PVIV structure back to an IV structure. The latter is smaller but the saving of memory would be tiny - not enough to justify the work. So, the PVIV structure remains, and it still points to the memory allocated to hold the string value, which still has the old, but no longer correct string value of the variable. It's OK that the string value is incorrect because the POK and pPOK flags are off, so the value will not be used. This wastes some memory, but saves some CPU.

    Then you print the value of $a. Again, a string value is needed. While the PVIV structure has a pointer to a string value, the POK and pPOK flags in the SV are off, so this value isn't used. Instead, perl again converts the current integer value to a string and prints that correct value. And, again, perl saves this value in case it might be used again. So, after printing Dump produces:

    SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 5 PV = 0x1dbdf84 "5"\0 CUR = 1 LEN = 4

    Again there are both integer and string values, and they are current and consistent. The IOK, POK, pIOK and pPOK flags are all set so that in subsequent operations these value might be used.

    Note also that the new string value is in the same bit of memory that the original string value was in. No additional memory was needed, so no new memory was allocated. The original memory was re-used. A lot of work has gone into minimizing expensive operations for the sake of performance.

    You might try extending your program, assigning a long string value to $a and then dumping it again. If you did, you would see that the same SV and PVIV structures were in use but the IOK and pIOK flags were off and the integer value in the PVIV remained unchanged and the long string was contained in newly allocated memory, as it wouldn't fit in the block originally allocated to hold the previous single character value.

Re: PV value
by sundialsvc4 (Abbot) on Jul 12, 2012 at 20:43 UTC

    Ahh ... “Simplify!   Simplify!!”

    perl -e 'my $a; $a=4; $a eq "13"; $a++; print "$a\n";'

    Or simply...

    perl -e 'my $a; $a=4; $a++; print "$a\n";'

    (You see, the do-nothing equality test does nothing ...   It evaluates a result, which happens to be false, and then throws it away.   Did that cause a to-string conversion side effect?   Maybe, maybe not ... who cares.)

    When you strip out all of the extraneous “fluff,” you assigned a variable the value 4, then incremented it, and wound up with 5.

    Internally, like every good language system, Perl is always lazy.   It won’t generate a string or even discard the old one until it has to, since even the microseconds required to do things like this can add up.   (Especially memory management.)   Macros and such are provided in the implementation to ensure (transparently to you...) that this “lazy” work has been done if it needs doing.   Just use them, as they are meant to be used, and be done:   if the currently stored value is stale, then it will be replaced before you get it such that what you get is never stale, and that’s all you need to be concerned with.   Don’t be concerned, because then your code gets clever, and clever code works in-test but fails under-load.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://981463]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2018-01-18 06:57 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (206 votes). Check out past polls.