http://www.perlmonks.org?node_id=1050502

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

I'm using Devel::Gladiator to get a list of all refs in use by Perl, which I want to (among other things) calculate the allocated size of with Devel::Size. This is the only way I could find to profile memory usage of unknown variables with reasonable accuracy without requiring a custom recompile of Perl to enable Perl malloc.

It almost works. Unfortunately, Devel::Size is segfaulting trying to calculate the size() of a handful of SCALAR refs (and so far no other kind of ref). So far the affected deref'd scalars contain variable names used/exported by various core pragmas, specifically, one of (no particular order):

$VERSION $XS_VERSION %DeadBits %Bits %Offsets %EXPORT_TAGS $Verbose $ExportLevel $Debug %Cache @EXPORT_OK @ISA

Here's a short script that demonstrates the issue. I've tried this on 5.14, 5.17.x, and 5.18.1, and crashes every time I run it.

use strict; use warnings; use Devel::Gladiator qw/walk_arena/; use Devel::Size qw/size/; my $arena = walk_arena(); my $i = 0; $| = 1; for (@$arena) { next unless ref eq 'SCALAR'; next if not defined $$_; printf '%4d : %16s : "%s" :', $i++, $_, $$_; print size($_); print "\n"; } @$arena = ();

I get output like:

0 : SCALAR(0xf8a4f8) : "$" :56 1 : SCALAR(0xf8a510) : "::" :128 . . 21 : SCALAR(0xf3bbb0) : "1.03" :56 22 : SCALAR(0xf3bc10) : "Devel::Size" :85 23 : SCALAR(0xf3bc28) : "$VERSION" :Segmentation fault (core dumped)

The crash occurs on size($_) (or total_size($arena)), not when printing $$_. I'm not surprised to have issues working with every SV in existence. My best workaround so far has been to use length() to put a lower bound on the size of scalars, instead of size(). This obviously can be wrong by an arbitrarily large factor, as in $ooo = 'o' x 2**20; $ooo = '';, which leaves $ooo with a length of 0, and a size over 1 MB. I could also skip scalars whose contents match any of the above strings, but that's thousands of string comparisons, and without knowing why these specific refs cause a core dump, this seems like the kind of hack that is likely to blow up in my face if another ref with the same problem comes along later.

So, I ask, can anyone shed any light on what's going on, here? I'm more than happy to file a bug if I'm not doing something stupid, but I'd be even happier to learn a stable way to iterate all refs in existence and calculate their sizes, or at least safely skip the few that are going to be problematic. Hopefully this all makes sense.

Replies are listed 'Best First'.
Re: Segfault with Devel::Size
by Anonymous Monk on Aug 22, 2013 at 10:20 UTC

    use Devel::Peek; Dump( $evilscalar );

    Also report Devel::Size version, upgrade if yours is old

      Dump produces something like this on values that core dump with size() (the Scalar::Util here is due to me including it for more testing since my first post. Others have come from core pragmas such as warnings):

      SV = IV(0x15fe438) at 0x15fe448 REFCNT = 2 FLAGS = (ROK) RV = 0x15cfc58 SV = PVMG(0x15b8c50) at 0x15cfc58 REFCNT = 2 FLAGS = (POK,pPOK,SCREAM,VALID,OUR,EVALED) COP_LOW = 253 COP_HIGH = 268 PV = 0x1581bc0 "$VERSION"\0 CUR = 8 LEN = 16 OURSTASH = 0x15c94e8 "Scalar::Util" RARE = 12 PREVIOUS = 0 USEFUL = 253

      I'm using Devel::Size 0.79, which is the latest on CPAN (including development releases).