有关背景信息,请参阅此related question。
注意:当我说“无效引用”时,我指的是指向无数据的引用。
假设我们有以下包含循环引用的数据结构:
+-----------------------------------------------------+
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$parent -->+============+ [ Hash ] |
[ ] +==========+ |
[ children --->[ Array ] |
[ ] [ ] |
+==========+ [ 0: ---------+ |
[ ] | |
+==========+ | |
| |
+--------------------------------------------------+ |
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$child --->+============+ [ Hash ] |
[ ] |
[ parent: ----------------------+
[ ]
+==========+
我知道我可以使用Scalar::Util
的weaken
函数来“削弱”引用。 。 。但是如果我从parent->child
削弱参考并且从child->parent
削弱参考,然后$child
或$parent
超出范围,而不是另一个,会发生什么?< / p>
示例: $parent
超出范围,因此引用已消失。
+-----------------------------------------------------+
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
+============+ [ Hash ] |
[ ] +==========+ |
[ children --->[ Array ] |
[ ] [ ] |
+==========+ [ 0: ---------+ |
[ ] | |
+==========+ | |
| |
would this break the link? ------------> X X
| |
+--------------------------------------------------+ |
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$child --->+============+ [ Hash ] |
[ ] |
[ parent: ----------------------+ <--- would this parent object pointer now be invalid?
[ ]
+==========+
如果我这样做,然后“父”超出范围,那么 是否会从内存中删除父对象,因为该对象的Perl内部引用计数为0? < / strong>我问这个,因为如果$child
仍然存在并且需要使用来自父对象的一些数据,这会导致问题,因为子对象现在会持有指向父对象的无效指针。
答案 0 :(得分:7)
my $x = { };
+============+ +==========+
$x -----> [ Reference ------->[ Hash ]
[ REFCNT=1 | [ REFCNT=1 ]
+============+ [ ]
+==========+
my $y = $x;
+============+ +==========+
$x -----> [ Reference ------->[ Hash ]
[ REFCNT=1 | +-->[ REFCNT=2 ]
+============+ | [ ]
| +==========+
+============+ |
$y -----> [ Reference ----+
[ REFCNT=1 |
+============+
weaken($y);
+============+ +==========+
$x -----> [ Reference ------->[ Hash ]
[ REFCNT=1 | +-->[ REFCNT=1 ]
+============+ | [ BACKREFS ---+
| +==========+ |
+============+ | |
$y -----> [ Weak Ref -----+ |
+--> [ REFCNT=1 | |
| +============+ |
+--------------------------------------+
除了在引用中设置WEAKREF
标志外,引用变量的引用计数已降低,并且已创建反向引用。
如果$y
超出范围,则第二个引用的REFCNT将降为零,这将释放引用。这通常会丢弃散列的引用计数,除了释放的引用是弱引用。因此,它只会将自己从反向引用列表中删除。
+============+ +==========+
$x -----> [ Reference ------->[ Hash ]
[ REFCNT=1 | [ REFCNT=1 ]
+============+ [ ]
+==========+
如果$x
超出范围,第一个引用的REFCNT将降为零,这将释放引用,这将使哈希的引用计数降为零,这将导致哈希被释放。作为其中的一部分,每个反向引用的变量都将成为undef。
+============+
$y -----> [ Undefined |
[ REFCNT=1 |
+============+
此时print("$y->{foo}\n");
将会嘶哑(退出并显示错误消息,而不是分段违规),您可以通过检查是否先定义$y
来避免这种情况。