Perl 内部结构详解 -- PerlGuts Illustrated (2 SV)

_SV_HEAD and struct sv

下面来看一下最简单的类型struct sv,代表了SV,GV,CV,AV,HV,IO的通用结构。如下图所示:


第一个字段Any可以指向任意结构,除了RV,所有的其他类型都是由Any指向的附加数据来实现。
第二个字段REFCNT表明了有多少pointers引用了这个object。初始置为1,当有pointers指向它或者被销毁的时候,这个值需要相应的加1或者减1,当值为0的时候,内存释放。
第三个字段包含了FLAGS & TYPE,是一个32 bit unsigned int。如下图:


常见的flags见下边具体示例。

C:\>perl -MDevel::Peek -e "Dump $a"
SV = NULL(0x0) at 0x182a9fc
  REFCNT = 1
  FLAGS = ()

C:\>perl -MDevel::Peek -e "Dump \$a"
SV = RV(0x299158) at 0x29914c
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x182a9fc
  SV = NULL(0x0) at 0x182a9fc
    REFCNT = 2
    FLAGS = ()


SvIV and SvNV

整数和小树,结构如图所示:


C:\>perl -MDevel::Peek -e "$a = 123; Dump $a"
SV = IV(0x182aa20) at 0x182aa24
  REFCNT = 1
  FLAGS = (IOK,pIOK)
  IV = 123

C:\>perl -MDevel::Peek -e "$a = 123.9; Dump $a"
SV = NV(0x184882c) at 0x182aa2c
  REFCNT = 1
  FLAGS = (NOK,pNOK)
  NV = 123.9

SvPV

字符串,结构如图所示:


除了SV以外,额外的结构xpv被分配,它包含三部分:

PVX 指向实际的字符串。
CUR 标记字符串的长度,PVX+CUR 处的字符应该为'\0',标记字符串的结束。
LEN 标记内存分配给char * 的长度,以4为增量。

POK标记表示PVX所指向的内存包含有效字符串,否则所包含的字符串无效。

C:\>perl -MDevel::Peek -e "$a = 't'; Dump $a"
SV = PV(0x296fec) at 0x182aa24
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x182472c "t"\0
  CUR = 1
  LEN = 4

C:\>perl -MDevel::Peek -e "$a = 'test'; Dump $a"
SV = PV(0x296fec) at 0x182aa2c
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x182466c "test"\0
  CUR = 4
  LEN = 8 (随着长度增加,以4为增量)

C:\>perl -MDevel::Peek -e "$a = 'test'; $a = undef; Dump $a"
SV = PV(0x296ffc) at 0x182aa34
  REFCNT = 1
  FLAGS = ()  (包含字符串,但是无效)
  PV = 0x1824674 "test"\0
  CUR = 4
  LEN = 8

SvOOK

为了提高移除字符串开头字符的速度,使用了OOK标记,IVX存储着偏移量,结构如图所示:


C:\>perl -MDevel::Peek -e "$a = 'xtesting'; $a=~s/.//; Dump $a"
SV = PVIV(0x182005c) at 0x182aa4c
  REFCNT = 1
  FLAGS = (POK,OOK,pPOK)
  IV = 1  (OFFSET)
  PV = 0x182467d ( "x" . ) "testing"\0
  CUR = 7
  LEN = 11

SvPVIV and SvPVNV

类似字符串,但是PVIV储存了额外的整数或者小数信息,可以根据flag直接进行数学运算,结构如图所示:


C:\>perl -MDevel::Peek -e "$a = '123.0'; 0+$a; Dump $a"
SV = PVNV(0x29838c) at 0x182aa34
  REFCNT = 1
  FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 123
  NV = 123
  PV = 0x1824674 "123.0"\0
  CUR = 5
  LEN = 8

C:\>perl -MDevel::Peek -e "$a = '123testing'; 0+$a; Dump $a"
SV = PVNV(0x298394) at 0x182aa34
  REFCNT = 1
  FLAGS = (POK,pIOK,pNOK,pPOK)
  IV = 123
  NV = 123
  PV = 0x1824674 "123testing"\0
  CUR = 10
  LEN = 12

SvRV

类似指针,指向任意其他结构,结构如图所示:

C:\>perl -MDevel::Peek -e "$a = '123testing'; $b = \$a ; Dump $b"
SV = RV(0x182ab68) at 0x182ab5c
  REFCNT = 1
  FLAGS = (ROK)
  RV = 0x182aa4c
  SV = PV(0x296ffc) at 0x182aa4c
    REFCNT = 2
    FLAGS = (POK,pPOK)
    PV = 0x182467c "123testing"\0
    CUR = 10
    LEN = 12



你可能感兴趣的:(Perl 内部结构详解 -- PerlGuts Illustrated (2 SV))