Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Circular references and Garbage collection.

by DigitalKitty (Parson)
on Aug 02, 2002 at 23:19 UTC ( #187246=perlquestion: print w/replies, xml ) Need Help??

DigitalKitty has asked for the wisdom of the Perl Monks concerning the following question:

Hi all.

A former college professor of mine and I were discussing memory leaks and garbage collection in various scripting languages the other day, and he asked me how this issue was handled in perl ( he bought 'Learning Perl - 3rd edition' last week ). After explaining what I knew about references ( I'm still learning ), he asked me if I could research the topic so we could discuss it in more depth.

So far, I have learned that perl handles this topic through a mechanism called reference counting. It seems each block of memory has an internal reference 'count' that stores the number of references which contain an address. If / When this number becomes zero, the memory that occupied that space is released ( freed ).

{ # Start of naked block. my $ref; { my $num = 20; $ref = \$num; } } #End of naked block.

When $num is created, the reference count becomes 1. Then the reference count is incremented to 2 when $ref is assigned a reference to $num. When we reach the end of the inner block, $num goes out of scope and we can no longer reference it through $num. This has the effect of decrementing the reference count by 1. At the end of the outer block, $ref goes out of scope thereby dropping the reference count to zero. This will free any memory previously occupied.

The problem occurs when one reference refers to another.
{ my $ref; my $ref2 = \$ref; $ref = \$ref2; }

The reference cannot drop to zero and the memory it is occupying will never be freed ( the dreaded memory leak ). This can bring a machine to it's knees if left 'unattended'. Does anyone know of an efficient way to break circular references? Aside from assigning a value to the scalar $ref ( i.e. $ref = 15 ), I don't see a solution.

Thanks in advance,

Replies are listed 'Best First'.
Re: Circular references and Garbage collection.
by theorbtwo (Prior) on Aug 03, 2002 at 00:09 UTC

    There's generaly three ways to get around this: Don't use circular refs, break them yourself (BTW, it's more clear to say $ref=undef or undef $ref then $ref=15), or use what is called a "weak reference", which is a referance that does not increase the refcount of a variable (BTW, variables, not blocks, have refcounts. (Except for coderefs, which in some ways /are/ variables.) Read WeakRef for details on using weak references.

    Perl6 is slated, BTW, to have a more advanced GC system. This will be faster, and not have problems with circular refs, but will have it's on problems. Currently, destructors (IE DESTROY methods) are run as soon as possible after the variable has gone out of scope/become unreferancable. Under most forms of GC, this will become delayed until the next dead-object-detection run, so there will often be a delay. While this isn't important for the majority of objects, it does become imporant for things like file locks and transactions, where you want the live time to be as short as possible.

    BTW, I'm no internals wizard. Take this all with a CC or so of salt.

    Confession: It does an Immortal Body good.

Re: Circular references and Garbage collection.
by sauoq (Abbot) on Aug 02, 2002 at 23:34 UTC
    The solution is either to avoid creating circular references or to be sure you break them yourself. This is documented in perlobj. Arguably, it should be documented elsewhere as well; perhaps it should be in perlref.

    Some say this is a failing of Perl's GC strategy. It can also be regarded as a strength. It greatly simplifies things while putting only a small burden on the programmer. If you are using circular references, you are probably sophisticated enough to handle breaking them yourself.

    "My two cents aren't worth a dime.";
Re: Circular references and Garbage collection.
by dws (Chancellor) on Aug 03, 2002 at 05:38 UTC
    A former college professor of mine and I were discussing memory leaks and garbage collection in various scripting languages the other day, and he asked me how this issue was handled in perl ...

    You may already have background in this, though for the benefit of those reading on...

    There are two principle approaches to memory management. One is to keep reference counts on objects, freeing the object when the count reaches zero. It's more work up front, but memory is freed promptly. One downside is that self-referential structures never reach zero reference counts, and hence are never freed. Perl5 uses this approach.

    The second scheme is to periodically sweep through memory, tracing out objects that are reachable through known starting points (e.g., global variables, stack frames), and freeing anything that isn't reachable. There's ongoing overhead, but garbage collection can take noticeable time (though there are many clever optimizations that can make this approach run quickly). Self referential structures that are not otherwise reachable do get freed. Most Java implementations use this approach.

Re: Circular references and Garbage collection.
by Anonymous Monk on Aug 03, 2002 at 01:41 UTC
    There are several strategies to break circular references.

    The simplest for many applications is to protect your entire circular datastructure with an object that you use to access it. Then give that object a DESTROY method that breaks all of the internal references so the entire mess will be garbage collected in time.

Re: Circular references and Garbage collection.
by BUU (Prior) on Aug 03, 2002 at 05:03 UTC
    So when you create a 'hard reference', it increments the ref counter. However, what happens if you use a soft ref? surely $baz='foo'; print ${'baz'} wont muck with the ref counter?
      Symbolic references only can access global variables which never clean themselves up because they are always pointed at by the package table. This is in addition to all of the other reasons that it is stupid to use symbolic references when you have any decent alternative.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://187246]
Approved by ChemBoy
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2023-04-01 17:28 GMT
Find Nodes?
    Voting Booth?

    No recent polls found