- publishing free software manuals
Perl Language Reference Manual
by Larry Wall and others
Paperback (6"x9"), 724 pages
ISBN 9781906966027
RRP £29.95 ($39.95)

Sales of this book support The Perl Foundation! Get a printed copy>>>

16.9 Two-Phased Garbage Collection

For most purposes, Perl uses a fast and simple, reference-based garbage collection system. That means there's an extra dereference going on at some level, so if you haven't built your Perl executable using your C compiler's -O flag, performance will suffer. If you have built Perl with cc -O, then this probably won't matter.

A more serious concern is that unreachable memory with a non-zero reference count will not normally get freed. Therefore, this is a bad idea:

{
    my $a;
    $a = \$a;
}

Even though $a should go away, it can't. When building recursive data structures, you'll have to break the self-reference yourself explicitly if you don't care to leak. For example, here's a self-referential node such as one might use in a sophisticated tree structure:

sub new_node {
    my $class = shift;
    my $node  = {};
    $node->{LEFT} = $node->{RIGHT} = $node;
    $node->{DATA} = [ @_ ];
    return bless $node => $class;
}

If you create nodes like that, they (currently) won't go away unless you break their self reference yourself. (In other words, this is not to be construed as a feature, and you shouldn't depend on it.)

Almost.

When an interpreter thread finally shuts down (usually when your program exits), then a rather costly but complete mark-and-sweep style of garbage collection is performed, and everything allocated by that thread gets destroyed. This is essential to support Perl as an embedded or a multithreadable language. For example, this program demonstrates Perl's two-phased garbage collection:

#!/usr/bin/perl
package Subtle;
sub new {
    my $test;
    $test = \$test;
    warn "CREATING " . \$test;
    return bless \$test;
}
sub DESTROY {
    my $self = shift;
    warn "DESTROYING $self";
}
package main;
warn "starting program";
{
    my $a = Subtle->new;
    my $b = Subtle->new;
    $$a = 0;  # break selfref
    warn "leaving block";
}
warn "just exited block";
warn "time to die...";
exit;

When run as /foo/test, the following output is produced:

starting program at /foo/test line 18.
CREATING SCALAR(0x8e5b8) at /foo/test line 7.
CREATING SCALAR(0x8e57c) at /foo/test line 7.
leaving block at /foo/test line 23.
DESTROYING Subtle=SCALAR(0x8e5b8) at /foo/test line 13.
just exited block at /foo/test line 26.
time to die... at /foo/test line 27.
DESTROYING Subtle=SCALAR(0x8e57c) during global destruction.

Notice that "global destruction" bit there? That's the thread garbage collector reaching the unreachable.

Objects are always destructed, even when regular refs aren't. Objects are destructed in a separate pass before ordinary refs just to prevent object destructors from using refs that have been themselves destructed. Plain refs are only garbage-collected if the destruct level is greater than 0. You can test the higher levels of global destruction by setting the PERL_DESTRUCT_LEVEL environment variable, presuming -DDEBUGGING was enabled during perl build time. See "PERL_DESTRUCT_LEVEL" (perlhack) in the Perl C API and Internals Manual for more information.

A more complete garbage collection strategy will be implemented at a future date.

In the meantime, the best solution is to create a non-recursive container class that holds a pointer to the self-referential data structure. Define a DESTROY method for the containing object's class that manually breaks the circularities in the self-referential structure.

ISBN 9781906966027Perl Language Reference ManualSee the print edition