Perl 通过引用计数(reference counting)实现自动内存管理。当你构建嵌套结构(例如哈希中的数组)时,任何容器的每个元素都会增加或减少对某个对象的引用计数。当引用计数变为零时,内存会被自动释放。
特别要注意循环引用,Perl 不会自动释放这些引用,这是处理嵌套结构时的经典陷阱。Perl 还通过 Scalar::Util 模块支持弱引用,这可以打破循环:弱引用不会增加引用计数。
my %hash_of_arrays; $hash_of_arrays{"nums"} = [1,2,3]; $hash_of_arrays{"words"} = ["apple", "banana"];
my $a = {}; my $b = { next => $a }; $a->{next} = $b; # 这里产生了循环 dump($a); # 使用 Data::Dumper 查看结构
为了避免内存泄漏,可以使用弱引用:
use Scalar::Util qw(weaken); $a->{next} = $b; weaken($a->{next}); # 现在 $a->{next} 是弱引用
如果在 Perl 中仅删除包含数组和哈希之间循环引用的外部变量,内存会发生什么?
正确答案: 任何对象的引用计数都不会归零,因为每个对象都会引用另一个对象;内存不会被释放 — 会发生内存泄漏!必须手动断开循环(例如,通过弱引用)。
my $arr = []; my $h = { arr => $arr }; push @$arr, $h; # 现在 $arr 和 $h 形成了循环。在 undef $arr; undef $h; 后,内存不会被释放。
历史
历史
历史
在实现 CGI 应用程序中的缓存时,决定使用复杂的相互关联结构(数组和哈希)。由于旧值没有正确归零,数组中的一个元素继续引用整个结构的哈希,导致在 HTTP 请求之间内存未被释放,从而导致 Apache 进程内存增长。