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

This is kind of just idle wondering, but does anyone have an idea of where 'REFCNT = 2147480012' arises from when dumping undef as a constant.

use Devel::Peek; my $scalar; Dump($scalar); Dump(undef); Dump(5); Dump('abc'); # SV = NULL(0x0) at 0x250b98c # REFCNT = 1 # FLAGS = (PADMY) # SV = NULL(0x0) at 0x9f3788 # REFCNT = 2147480012 # FLAGS = (READONLY) # SV = IV(0x250b998) at 0x250b99c # REFCNT = 1 # FLAGS = (PADTMP,IOK,READONLY,pIOK) # IV = 5 # SV = PV(0x261b534) at 0x25021b4 # REFCNT = 1 # FLAGS = (PADTMP,POK,READONLY,pPOK) # PV = 0x2716f54 "abc"\0 # CUR = 3 # LEN = 4

Replies are listed 'Best First'.
Re: Dumping undef as a constant produces strange REFCNT
by ikegami (Patriarch) on Aug 24, 2011 at 22:40 UTC

    Perl statically allocates three SVs: &PL_sv_undef (an undefined value), &PL_sv_yes (a true value) and &PL_sv_no (a false value). Being statically allocated, they cannot be freed. Perl calls them "immortal".

    In order to prevent them from getting freed, the functions that get called to free scalars have special checks that prevent them from freeing immortal scalars.

    In order to avoid trying to free immortal scalars in the first place, their ref count is initially set very high, and their ref count is reset to that value ((~(U32)0)/2) should it ever reach zero.

    These SVs are used in a many places (e.g. &PL_sv_undef). Only allocating them once saves time.

    $ perl -E'say Internals::SvREFCNT($$_) for \undef, \!0, \!1;' 2147483625 2147483644 2147483647
Re: Dumping undef as a constant produces strange REFCNT
by BrowserUk (Patriarch) on Aug 24, 2011 at 21:44 UTC
    where 'REFCNT = 2147480012' arises

    I believe that it is an artificially high value set deliberately to ensure that the constant undef is never garbage collected.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Dumping undef as a constant produces strange REFCNT
by charlesboyo (Beadle) on Aug 24, 2011 at 21:45 UTC
    It appears that Perl keeps tabs, even on undefs. While the count may be a little off, loading Perl, loading Devel::Peek and compiling your code appears to have created that may undef. :) Surprising isn't it? Try this out:
    use Devel::Peek; Devel::Peek::Dump(undef); eval('require File::Find'); Devel::Peek::Dump(undef);
    produces on my system:
    SV = NULL(0x0) at 0x8ca1b0 REFCNT = 2147483597 FLAGS = (READONLY) SV = NULL(0x0) at 0x8ca1b0 REFCNT = 2147483005 FLAGS = (READONLY)
    While
    eval('require Devel::Peek'); Devel::Peek::Dump(undef); eval('require File::Find'); Devel::Peek::Dump(undef);
    produces:
    SV = NULL(0x0) at 0x34a1b0 REFCNT = 2147483602 FLAGS = (READONLY) SV = NULL(0x0) at 0x34a1b0 REFCNT = 2147483010 FLAGS = (READONLY)
    On each run, the difference between the two REFCNTs is 592. Although it seems strange that I end up with fewer REFCNTs.

      It does indeed seem to be counting down as more use/require etc statements are added or eval'd. In fact, any successful eval will also lower the count. Something as simple as eval('#') lowers the count by one.

      The below gives me the highest output count I can get of 2147483604. My guess would be that 2147483647, max val for signed long, is the starting point.

      I'm also curious whether this is some real count value or some artifact of Devel::Peek

      require Devel::Peek; Devel::Peek::Dump(undef); # SV = NULL(0x0) at 0x993788 # REFCNT = 2147483604 # FLAGS = (READONLY)

        I'm also curious whether this is some real count value or some artifact of Devel::Peek

        It's the real value of the REFCNT field, but it does not indicate the number of references to that scalar.

        My guess would be that 2147483647, max val for signed long, is the starting point.

        Yes, or more precisely, the midpoint of 32-bit unsigned ints (even on a 64-bit build).

        The max value wouldn't be good because it's possible to increase it.

        $ perl -E' sub show { say &Internals::SvREFCNT( \undef ); } show(); push @a, \undef for 1..5; show(); ' 2147483623 2147483628

        Of course, it's also possible to reduce it.

        $ perl -E' sub show { say &Internals::SvREFCNT( \undef ); } show(); { my @a; $#a = 5; } show(); ' 2147483623 2147483617