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

Hi again, Been a while since my last post. I have started working heavily with Perl modules...mostly writing custom modules that utilize XML::Simple(). My question is, is there any problems and/or concerns with doing my own memory management with the custom modules? ... i.e. seting unused objects back to undef?

I come from a heavy C/C++ background...thus, there is an inherit "want" to manage this stuff explicitly...

For example...A typical module would get supplied a filename to an XML document file. Then do the following...
- Create and XML::Simple()
- Read in the document.
- Store the elements into a local hash.
- set XML::Simple() stuff = undef; # memory cleanup
A small code snippet looks like the following...

# MAIN PRORGRAM : ... # else { $gtheProcess = undef; $gtheProcess = new Registry ( file => $strDir."/".$strProcess ,verbose => $gblnVerbose ); } <snip> # REGISTRY MODULE : new () # sub new { my $class = shift; my $self = {}; my $theOptions = { @_ }; ....lots of code... if ( exists($self->{file}) ) { my $gxmlFile = $self->{file}; if ( open( ghdlFile, "< $gxmlFile" ) == 1 ) { close ghdlFile; # XML : Create a new XML object... my $gxmlObject = XML::Simple->new(); # OPEN : Open the configuration file... my $gxmlDocument = $gxmlObject->XMLin($gxmlFile); # CAPTURE : Grab all the configuration elements from the f +ile... foreach my $lstrKey (keys (%{$gxmlDocument})) { $self->{$lstrKey} = $gxmlDocument->{$lstrKey}; } # end : foreach # FREE : Free up objects... # $gxmlDocument = undef; $gxmlObject = undef; } # end : if ( open( cfgFH, "< $gxmlConfigFile" ) == 1 ) } # if ( exists($self->{file}) ) return( bless($self, $class) ); } # end : new()
Does Perl like/dislike explicit memory management by setting the above $gxmlDocument and $gxmlObject = undef?

tia,

adym

Replies are listed 'Best First'.
Re: Memory Management...
by Abigail-II (Bishop) on Feb 03, 2004 at 16:54 UTC
    Does Perl like/dislike explicit memory management by setting the above $gxmlDocument and $gxmlObject = undef?
    Perl has no feelings, so it couldn't care less. However, you are wasting resources this way. $gxmlDocument and $gxmlObject are about to go out of scope, after which Perl will free the memory they use, which will most likely cascade in the freeing of the memory they point too. But before that, you first create two new SVs (both undef), each taking at least 12 bytes, more on 64 bit platforms. After that, the objects go out of scope cleaning up the newly created SVs.

    The end result is the same. Both letting Perl handle the memory, and you doing the undef will arrive at the foot of the hill. But with your method, you first go uphill.

    If you want to take the long road, use your undefs. If you want to be efficient, let Perl do the job.

    Abigail

      TMTOWTDI. :)

      I like Abigail's suggestion here. Just let it go out of scope and let perl handle things. Perl is good at that.
Re: Memory Management...
by welchavw (Pilgrim) on Feb 03, 2004 at 17:04 UTC

    As long as your result is not rendered incorrect, you will find Perl will not hesitate to run your code. Whether code reviewers would tolerate is entirely another matter. Whether you are having the effect you intend is another.

    Do you *know* that setting to undef is freeing those objects immediately (or even soon) (update: especially see bean's note below re: undef $x vs. $x = undef)? Or are you making assumptions about the garbage collector's behavior? Would you, at a C code review, accept inline assembly bit-fiddling tricks, or would you insist that the C operators be used to the same effect? Your answers to these questions should guide you, IMHO.

    ,welchavw

Re: Memory Management...
by Fletch (Bishop) on Feb 03, 2004 at 17:14 UTC

    So long as you have no reference loops (e.g. $a->{next} = \$b; $b->{next} = \$c; $c->{next} = \$a) you'll be fine. If you do have loops or what not you'll need to explicitly break them (see HTML::Element for a real world example).

Re: Memory Management...
by ysth (Canon) on Feb 03, 2004 at 17:46 UTC
    If no persistent reference to the $gxmlFoo's is there, the undef is unnecessary; perl will clean-up my() variables automatically at the end of their scope.

    If there is a persistent reference, your =undef's will be The Wrong Thing To Do (TM).

    The only case where you would need to do anything like that is where there is a (direct or indirect) circular reference, e.g. my $a; $a = \$a

Re: Memory Management...
by hardburn (Abbot) on Feb 03, 2004 at 20:34 UTC

    I come from a heavy C/C++ background...thus, there is an inherit "want" to manage this stuff explicitly...

    Don't think of it as Perl's fault for not generally allowing you to do your own memory management. Instead, think of it as C/C++'s fault for not doing it for you by default. Garbage Collectors are a well-researched topic in CS and they've gotten pretty good as long as you're not attempting to bolt them on to a language that didn't orginally support it. Perl's simple ref count GC has problems with circular refs (see above replies), but that's a fairly esoteric circumstance.

    ----
    I wanted to explore how Perl's closures can be
    manipulated, and ended up creating an object
    system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Re: Memory Management...
by bean (Monk) on Feb 04, 2004 at 00:13 UTC
    As everyone has already mentioned, Perl has garbage collection and you don't need to worry about it. However, if you did for some reason need to free up some memory the way to do that would be
    undef $x;
    not
    $x = undef;
    The former is equivalent to the C "free" function, whereas with the latter you are moving your pointer/reference off your object - if this were C code, you'd have just lost your allocated memory and leaked it. This is Perl, so the garbage collector takes care of you and it works, but not for the reason you think it does.

    There is one case where you need to manage your memory in Perl, and that's when you're using SWIG to allocate memory in C from Perl:
    use SwiggedCLib; #allocate a struct in C my $pointer = SwiggedCLib::createIt(); #do something with the struct my $result = SwiggedCLib::doSomething( $pointer ); #destroy the struct - Perl doesn't know how SwiggedCLib::destroyIt( $pointer );
    When I did this with SWIG/C/Perl/Tcl, I vaguely remember having to undef the $pointer that held the struct or I would get a fatal exception from the garbage collector. However, that may have been in Tcl, not Perl. And I may have been doing something wrong. I'll update this when I get home and can look at the code...

    Update

    I just checked the code, and I did need to do
    undef $pointer;
    after freeing the memory using a SWIGged C function (which also set the C pointer to NULL). The error I got if I didn't may have been a segfault - I don't remember, I just know it was a showstopper. It leaves open the possibility that I was doing something wrong - it worked fine in Tcl, though...