下面来看一下最简单的类型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 = ()
整数和小树,结构如图所示:
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
字符串,结构如图所示:
除了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
为了提高移除字符串开头字符的速度,使用了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
类似字符串,但是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
类似指针,指向任意其他结构,结构如图所示:
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