我的问题是关于 Perl 如何在内部管理对象的数据。
在 Perl 中创建对象时,新的子例程通常会返回对祝福对象的引用。
以如下代码为例:
# Create a new object
my $object = Object->new(%data1);
# Create a new object with the same variable
$object = Object->new(%data2);
从第一次调用
new
我们创建一个 $object
引用了一些有福的%data1
Visual representation:
The "\" symbolizes a reference.
$object ════> \{bless %data1}
This would look as follows in memory:
The "&" symbolizes an address
MEMORY:
----------------------------------
&{bless %data1} ════> bless %data1
然后第二次调用
new
$object
的值改为引用其他一些有福的%data2
Visual representation:
$object ══/ /══> \{bless %data1} # The connection to %data1 is broken
║
╚═══════════> \{bless %data2}
Now memory would look like this:
MEMORY:
----------------------------------
&{bless %data1} ════> bless %data1
&{bless %data2} ════> bless %data2
现在的问题是
$object
不再存储引用 \{bless %data1}
,地址&{bless %data1}
并且存储在该地址的任何数据都将永远丢失。再也无法从脚本访问存储在该位置的数据了。我的问题是。 . . Perl 是否足够聪明,可以删除存储在
&{bless %data1}
中的数据?一旦对该数据的引用永远丢失,或者 Perl 是否会将这些数据保存在内存中,从而可能导致内存泄漏?
最佳答案
给定
package Object {
sub new { my $class = shift; bless({ @_ }, $class) }
}
my $object = Object->new( a => 1, b => 2 );
在第二次分配之前,你有
+============+ +==========+
$object -->[ Reference ---->[ Blessed ]
+============+ [ Hash ]
[ ] +==========+
[ a: --------->[ 1 ]
[ ] +==========+
[ ]
[ ] +==========+
[ b: --------->[ 2 ]
[ ] +==========+
+==========+
(箭头代表指针。)
Perl 使用引用计数来确定何时释放变量。作为赋值的一部分,名称(引用)当前引用的变量的引用计数将递减,导致它被释放[1]。这将减少哈希的引用计数,导致它被释放[1]。这将减少值的引用计数,导致它们被释放[1]。
在 Perl 中,当您有循环引用时会发生内存泄漏。
{
my $parent = Node->new();
my $child = Node->new();
$parent->{children} = [ $child ];
$child->{parent} = $parent;
}
在退出区 block 之前,您有
$parent +----------------------------------------------------+
| | |
| +============+ +-->+==========+ |
+-->[ Reference -------->[ Blessed ] |
+============+ [ Hash ] |
[ ] +==========+ |
[ children --->[ Array ] |
[ ] [ ] +============+ |
+==========+ [ 0: --------->[ Reference ----+ |
[ ] +============+ | |
+==========+ | |
| |
$child +-------------------------------------------------+ |
| | |
| +============+ +-->+==========+ |
+-->[ Reference -------->[ Blessed ] |
+============+ [ Hash ] |
[ ] +============+ |
[ parent: ---->[ Reference ----------------------+
[ ] +============+
+==========+
存在 block 后,您有
+----------------------------------------------------+
| |
+-->+==========+ |
[ Blessed ] |
[ Hash ] |
[ ] +==========+ |
[ children --->[ Array ] |
[ ] [ ] +============+ |
+==========+ [ 0: --------->[ Reference ----+ |
[ ] +============+ | |
+==========+ | |
| |
+-------------------------------------------------+ |
| |
+-->+==========+ |
[ Blessed ] |
[ Hash ] |
[ ] +============+ |
[ parent: ---->[ Reference ----------------------+
[ ] +============+
+==========+
内存没有被释放,因为所有内容仍然被引用,因为有一个引用周期。由于您无法访问此结构(没有变量名引用其中的任何内容),因此这是内存泄漏。
关于覆盖对象时的 Perl 内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31971633/