Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
覆盖对象时的Perl内存管理_Perl_Oop_Memory Management_Memory Leaks_Reference - Fatal编程技术网

覆盖对象时的Perl内存管理

覆盖对象时的Perl内存管理,perl,oop,memory-management,memory-leaks,reference,Perl,Oop,Memory Management,Memory Leaks,Reference,我的问题是Perl如何在内部管理对象的数据 在Perl中创建对象时,新的子例程通常会返回对对象的引用 以下面的代码为例: 从第一次调用new开始,我们创建了一个$object,它引用了一些受祝福的%data1 # Create a new object my $object = Object->new(%data1); # Create a new object with the same variable $object = Object->new(%data2); 视觉表现

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

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

以下面的代码为例:


从第一次调用
new
开始,我们创建了一个
$object
,它引用了一些受祝福的
%data1

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

# Create a new object with the same variable
$object = Object->new(%data2);
视觉表现:

“\”表示引用

这将在内存中显示如下:

“&”代表一个地址


然后在第二次调用
new
时,
$object
的值被更改为引用一些其他的
%data2

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

# Create a new object with the same variable
$object = Object->new(%data2);
视觉表现:

现在,内存将如下所示:


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


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

存在引用计数垃圾收集。“我没有在你的代码中看到任何会出错的东西,”他说。即使有,Scalar::Util和其他选项中也有削弱。

您误解了参数传递的工作方式
$object
成为一个新创建的引用,其内容可能会受到传递给构造函数的数据的影响
new
,但它不会引用散列
%data1
%data2
本身,因为
new
只提供这些散列的键/值内容

您的问题的底线似乎是Perl是否足够聪明,可以在不再使用对象时释放对象,答案是,是的

Perl保留对每个数据项的引用计数,如果该值降至零(即不再有任何方法可以访问该数据),则认为该数据可供重用

Perl导致内存泄漏的唯一情况是数据结构包含对自身的引用。在这种情况下,外部引用的数量可能会降至零,但数据本身不会被自己的引用删除,从而使计数不会降至零

避免使用包变量,只使用用
my
声明的词法变量也更安全。词法变量将在超出范围时自动销毁,从而减少它们可能包含的任何引用的数量。用
our
声明的包变量将在进程的另一个生命周期内存在,并且不会触发此保护


如果您进一步解释一下为什么需要这些信息,那么我相信您会得到更好的答案

Perl使用了一种称为引用计数的方法—它计算变量被引用的次数。它将数据保存在内存中,直到引用计数降至零

在您的示例中,一旦重新指定
$object
,创建的第一个对象将自动消失。但是有一个警告-如果在对象和
new
过程中创建循环引用,则不会发生这种情况。您可以在
Scalar::Util
中使用
delever
来处理此问题

您可以通过创建
DESTROY
方法来观察它,该方法在对象被“释放”时调用

给定

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        ]
                            [          ]   +==========+
                            +==========+
$parent               +----------------------------------------------------+
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
$child                +-------------------------------------------------+  |
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
                      +----------------------------------------------------+
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
                      +-------------------------------------------------+  |
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
(箭头表示指针。)

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


在Perl中,循环引用会导致内存泄漏

{
   my $parent = Node->new();
   my $child = Node->new();
   $parent->{children} = [ $child ];
   $child->{parent} = $parent;
}
在离开街区之前,你必须

           +============+   +==========+
$object -->[ Reference ---->[ Blessed  ]
           +============+   [ Hash     ]
                            [          ]   +==========+
                            [ a: --------->[ 1        ]
                            [          ]   +==========+
                            [          ]
                            [          ]   +==========+
                            [ b: --------->[ 2        ]
                            [          ]   +==========+
                            +==========+
$parent               +----------------------------------------------------+
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
$child                +-------------------------------------------------+  |
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
                      +----------------------------------------------------+
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
                      +-------------------------------------------------+  |
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
在存在块之后,您就有了

           +============+   +==========+
$object -->[ Reference ---->[ Blessed  ]
           +============+   [ Hash     ]
                            [          ]   +==========+
                            [ a: --------->[ 1        ]
                            [          ]   +==========+
                            [          ]
                            [          ]   +==========+
                            [ b: --------->[ 2        ]
                            [          ]   +==========+
                            +==========+
$parent               +----------------------------------------------------+
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
$child                +-------------------------------------------------+  |
 |                    |                                                    |
 |   +============+   +-->+==========+                                     |
 +-->[ Reference -------->[ Blessed  ]                                     |
     +============+       [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
                      +----------------------------------------------------+
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +==========+                      |
                          [ children --->[ Array    ]                      |
                          [          ]   [          ]   +============+     |
                          +==========+   [ 0: --------->[ Reference ----+  |
                                         [          ]   +============+  |  |
                                         +==========+                   |  |
                                                                        |  |
                      +-------------------------------------------------+  |
                      |                                                    |
                      +-->+==========+                                     |
                          [ Blessed  ]                                     |
                          [ Hash     ]                                     |
                          [          ]   +============+                    |
                          [ parent: ---->[ Reference ----------------------+
                          [          ]   +============+
                          +==========+
内存未被释放,因为存在引用循环,所以所有内容仍在被引用。由于您无法访问此结构(没有变量名引用其中的任何内容),因此这是内存泄漏


  • 假设没有其他引用(指向)这些变量

  • 你能详细说明一下吗?您似乎在说这不会是一个问题,但具体来说,Perl如何以一种不会发生这种情况的方式处理内存?我需要这些信息,因为我有创建对象并将其存储在变量中的代码,然后如果满足某些条件,它将使用相同的变量并创建一个新对象。这与问题中描述的情况基本相同。@tjwrona1992:好吧,但你和成千上万不需要问这个问题的程序员处于相同的情况。你遇到内存泄漏了吗?在我使用它的方式中,没有对自身的引用,所以我认为我是安全的。谢谢@Borodin@tjwrona1992:避免使用包变量,只使用用
    my
    声明的词法变量也更安全。词法变量将在超出范围时自动销毁,从而减少它们可能包含的任何引用的数量。用
    our
    声明的包变量将在进程的另一个生命周期内存在,并且不会触发此安全保护。我知道,我没有使用任何包变量。我只是想知道,在引用丢失(即使在词汇上下文中也可能发生)后,对象是否会保留在内存中。如果我