覆盖对象时的 Perl 内存管理

标签 perl oop memory-management memory-leaks reference

我的问题是关于 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/

    相关文章:

    c - 在 Shell 脚本或 Perl 脚本中对单词进行排序,然后对包含数字和字符的句子进行排序

    perl - 如何在 Perl DBI 日志文件中获取时间戳?

    perl - 将 Perl 与 emacs 编辑器结合使用

    java - 可能有多个 ArrayList 的 ArrayList

    memory-management - 哪些操作系统将释放内存泄漏?

    c++ - 如何优化大型内存数据库的分页

    c - gdb 报错,但程序运行正常

    python - 如何通过shell脚本编辑XML文件来更改所有数字,其中原始点除以1.3?

    algorithm - 如何适应需要成为应用程序一部分的新逻辑

    oop - 将指向私有(private)数据的指针发送给另一个类是一种良好的面向对象设计实践吗?