覆盖对象时的Perl内存管理

tjw*_*992 2 oop perl memory-leaks memory-management reference

我的问题是关于Perl如何在内部管理对象的数据.

在Perl中创建对象时,新子例程通常会返回对受祝福对象的引用.

以下面的代码为例:

# Create a new object
my $object = Object->new(%data1);

# Create a new object with the same variable
$object = Object->new(%data2);
Run Code Online (Sandbox Code Playgroud)

从第一次打电话到new我们创建一个$object引用一些祝福的人%data1

视觉表现:

"\"表示引用.

$object ????> \{bless %data1}
Run Code Online (Sandbox Code Playgroud)

这在内存中看起来如下:

"&"表示地址

MEMORY:
----------------------------------
&{bless %data1} ????> bless %data1
Run Code Online (Sandbox Code Playgroud)

然后用第二次调用new的值$object改为引用其他一些祝福%data2

视觉表现:

$object ??/ /??> \{bless %data1}  # The connection to %data1 is broken
   ?
   ????????????> \{bless %data2}
Run Code Online (Sandbox Code Playgroud)

现在内存看起来像这样:

MEMORY:
----------------------------------
&{bless %data1} ????> bless %data1
&{bless %data2} ????> bless %data2
Run Code Online (Sandbox Code Playgroud)

问题是现在$object不再存储引用\{bless %data1},地址&{bless %data1}和存储在该地址的任何数据将永远丢失.无法再从脚本访问存储在该位置的数据.

我的问题是...Perl是否足够聪明,&{bless %data1}一旦永久丢失对此数据的引用,就会删除存储的数据,或者Perl会将这些数据保留在内存中,从而可能导致内存泄漏吗?

ike*_*ami 7

特定

package Object {
   sub new { my $class = shift; bless({ @_ }, $class) }
}

my $object = Object->new( a => 1, b => 2 );
Run Code Online (Sandbox Code Playgroud)

在第二次任务之前,你有

           +============+   +==========+
$object -->[ Reference ---->[ Blessed  ]
           +============+   [ Hash     ]
                            [          ]   +==========+
                            [ a: --------->[ 1        ]
                            [          ]   +==========+
                            [          ]
                            [          ]   +==========+
                            [ b: --------->[ 2        ]
                            [          ]   +==========+
                            +==========+
Run Code Online (Sandbox Code Playgroud)

(箭头代表指针.)

Perl使用引用计数来确定何时释放变量.作为赋值的一部分,名称(引用)当前引用的变量的引用计数将递减,从而使其被释放[1].这将删除哈希的引用计数,导致它被释放[1].这将删除值的引用计数,导致它们被释放[1].


在Perl中,当您有循环引用时会出现内存泄漏.

{
   my $parent = Node->new();
   my $child = Node->new();
   $parent->{children} = [ $child ];
   $child->{parent} = $parent;
}
Run Code Online (Sandbox Code Playgroud)

在退出街区之前,你有

$parent               +----------------------------------------------------+
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
$child                +-------------------------------------------------+  |
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
Run Code Online (Sandbox Code Playgroud)

在存在块后,你有

                      +----------------------------------------------------+
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
                      +-------------------------------------------------+  |
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
Run Code Online (Sandbox Code Playgroud)

内存没有被释放,因为所有内容仍然被引用,因为有一个引用周期.由于您无法访问此结构(没有变量名称引用其中的任何内容),因此它是内存泄漏.


  1. 假设没有其他任何引用(指向)那些变量.

  • @Borodin,你错了。[`bless`](http://perldoc.perl.org/functions/bless.html)“告诉 REF 引用的东西它现在是 CLASSNAME 包中的一个对象。” 亲自查看如何使用 `perl -MDevel::Peek -e'Dump(bless(\%hash));'` 和 `perl -e'bless(\%hash); (\%hash)->foo'`。前者显示附加到哈希的 OBJECT 标志和 STASH 字段,而不是 ref。后者表明即使使用的引用是在调用 bless 之后创建的,对象的类也是已知的。 (2认同)