いままでぜんぜん気にしていなかったけどPerlのGCはリファレンスカウント方式らしい
なのでオブジェクトへの参照が作られるたびにリファレンスカウントを増やしていって
オブジェクトへの参照が破棄されたタイミングでリファレンスカウントが減ることになる
そしてリファレンスカウントが0になったタイミングでそのオブジェクトは開放される
$ perl -MDevel::Peek -e 'my $foo; Dump $foo; my $bar = \$foo; Dump $foo; undef $bar; Dump $foo;' SV = NULL(0x0) at 0xa96c18 REFCNT = 1 FLAGS = () SV = NULL(0x0) at 0xa96c18 REFCNT = 2 FLAGS = () SV = NULL(0x0) at 0xa96c18 REFCNT = 1 FLAGS = ()
REFCNT
がリファレンスカウント数
また、スコープを切ってあげるとオブジェクトへの参照が破棄されてリファレンスカウントが減る模様
$ perl -MDevel::Peek -e 'my $foo; Dump $foo; {my $bar = \$foo; Dump $foo;} Dump $foo;' SV = NULL(0x0) at 0x1dc6c18 REFCNT = 1 FLAGS = () SV = NULL(0x0) at 0x1dc6c18 REFCNT = 2 FLAGS = () SV = NULL(0x0) at 0x1dc6c18 REFCNT = 1 FLAGS = ()
なのでわりと簡単に循環参照を作るのことができててしまう
SV = NULL(0x0) at 0x24c9c60 REFCNT = 1 FLAGS = () SV = IV(0x24c9c50) at 0x24c9c60 REFCNT = 2 FLAGS = (ROK) RV = 0x24c9c60 SV = IV(0x24c9c50) at 0x24c9c60 REFCNT = 2 FLAGS = (ROK) RV = 0x24c9c60 SV = IV(0x24c9c50) at 0x24c9c60 REFCNT = 2 FLAGS = (ROK) RV = 0x24c9c60 SV = IV(0x24c9c50) at 0x24c9c60 REFCNT = 2 FLAGS = (ROK) RV = 0x24c9c60 SV = IV(0x24c9c50) at 0x24c9c60 REFCNT = 2 FLAGS = (ROK) RV = 0x24c9c60 Cycle (1): $$A => \$A
省メモリかつオブジェクトの破棄するタイミングを完璧にコントロールできるが
循環参照には気をつけないとメモリリークを起こしてしまう可能性もあるので
今後は意識しながらプログラミングしていこうと思った