Weak references#

Perl tracks object lifetime with reference counting. Every value knows how many references point at it; when the count drops to zero, the value is freed. This works well for tree-shaped data, where references flow one way, parent to child. It fails for cycles, where a chain of references eventually points back at something earlier in the chain. The cycle’s members keep each other alive even when nothing outside the cycle refers to them any more.

A weak reference is a reference that does not increment the referent’s reference count. It lets you point at something without keeping it alive. Weak references are Perl’s standard answer to reference cycles.

How a cycle leaks#

Consider a doubly-linked list node that holds both next and prev references:

sub new_node {
    my ($value) = @_;
    return { value => $value, next => undef, prev => undef };
}

my $a = new_node('A');
my $b = new_node('B');
$a->{next} = $b;
$b->{prev} = $a;

$a and $b each have a reference count of 2:

  • $a is referenced by the lexical $a and by $b->{prev}.

  • $b is referenced by the lexical $b and by $a->{next}.

When the lexicals go out of scope, their contribution drops:

  • $a drops to count 1 (only $b->{prev} left).

  • $b drops to count 1 (only $a->{next} left).

Neither reaches zero. Both nodes are unreachable from anywhere in your program, yet they keep each other alive for the life of the interpreter. That’s a leak.

Fixing the leak with weaken#

Scalar::Util::weaken turns an existing reference into a weak one. The reference still works for dereferencing; it just doesn’t count toward keeping the target alive.

The standard pattern: whichever direction you consider “back-pointer” or “parent pointer”, make that one weak.

use Scalar::Util qw(weaken);

my $a = new_node('A');
my $b = new_node('B');
$a->{next} = $b;
$b->{prev} = $a;
weaken $b->{prev};             # the back-pointer

Now $a’s reference count stays at 1 (only the lexical $a contributes; $b->{prev} is weak and does not count). When $a goes out of scope, $a is freed — and because freeing $a drops $b->{next}, $b is freed too. The whole structure collapses.

When a weak reference becomes undef#

If the referent is freed while a weak reference still exists, the weak reference automatically becomes undef. You never see a dangling pointer:

use Scalar::Util qw(weaken);

my $target = { name => 'alive' };
my $weak   = $target;
weaken $weak;

print defined $weak ? "yes\n" : "no\n";   # yes
undef $target;                             # last strong ref gone
print defined $weak ? "yes\n" : "no\n";   # no

defined $weak is the standard way to check whether the target is still there. See defined.

Where weak references belong#

The rule: use a weak reference for the “non-owning” pointer in any pair of references that would otherwise cycle.

  • Doubly-linked list. next owns; prev is weak.

  • Parent/child tree with parent pointers. children owns; parent on each child is weak.

  • Observer pattern. The subject holds weak references to its observers; observers hold strong references to the subject. When an observer drops its reference, it goes away; the subject’s entry for it turns to undef and can be swept.

  • Caches that shouldn’t keep entries alive. A cache whose values are weak references does not extend the lifetime of the cached objects.

isweak — inspecting a reference#

Scalar::Util::isweak tells you whether a given scalar holds a weak reference:

use Scalar::Util qw(weaken isweak);

my $x = { k => 1 };
my $y = $x;
print isweak($y) ? "weak\n" : "strong\n";   # strong
weaken $y;
print isweak($y) ? "weak\n" : "strong\n";   # weak

Useful mostly when debugging a lifetime problem. Production code rarely branches on isweak.

Common mistakes#

  • Weakening the wrong end. Weakening the “forward” pointer (the one that owns the successor) frees the successor immediately, before you ever use it. Weak goes on the back-pointer.

  • Weakening a lexical. weaken $ref where $ref is a fresh lexical referencing $target makes the lexical weak. If nothing else holds a strong reference to $target, it vanishes at the next statement and $ref becomes undef. Weak references belong in data-structure slots, not typically in local lexicals.

  • Assuming weak references are automatic. Perl does not detect cycles and weaken them for you. You have to opt in.

Beyond Scalar::Util#

Scalar::Util ships with Perl; it is always available. For more elaborate needs — WeakRef, Hash::Util::FieldHash — reach for CPAN. For ordinary code, weaken is all you need.

Where to go next#

You’ve finished the references tutorial. Good next reads:

  • The ref reference page — the full list of strings it returns, including blessed-object cases.

  • bless — how a plain hash reference becomes an object of a specific class.

  • The object-orientation tutorial, once you’re ready for classes built on top of the references you now understand.