Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

unreachable memory with a non-zero reference count

by Pickwick (Beadle)
on Jun 20, 2010 at 15:49 UTC ( [id://845638]=perlquestion: print w/replies, xml ) Need Help??

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

Hello all,

in the perl documentation I've read about some statements that could result in memory leaks, but I don't understand what the real problem is and if some code I use should be avoided because it has the same problem. I would be happy if someone could give me some advise and lighten my darkness.

Let me quote:

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; }

http://perldoc.perl.org/perlobj.html#Two-Phased-Garbage-Collection

Is the problem that $a is declared in the block, but never assigned with something and never used elsewhere? If I would assign $a a value from somewhere and do use it somewhere else, do I have the same problem?

I have code like the following:

sub foo { my $retVal = undef; $retVal = $someObject->bar()->doSomething(); $retVal = \$retVal; Log4perl->debug('retval: ', sub {$retVal}); return $retVal; }

The goal of the above is to let foo return a reference to a string, but just have to create that reference once and to use it as a return value and for logging purposes. Does this produces memory leaks like stated in the perl documentation?

Thanks for your hints.

Replies are listed 'Best First'.
Re: unreachable memory with a non-zero reference count
by Corion (Patriarch) on Jun 20, 2010 at 15:59 UTC

    Your code makes no sense:

    $retVal = $someObject->bar()->doSomething(); $retVal = \$retVal;

    You overwrite $retVal immediately. Maybe you meant:

    my $myVal = $someObject->bar()->doSomething(); $retVal = \$myVal; Log4perl->debug('retval: ', sub {$retVal}); return $retVal;

    Then, I think you won't have a memory leak, as the only thing that's keeping $myVal alive is the reference in $retVal. When that reference goes out of scope, also $myVal will get released.

      Your code makes no sense:
      ...
      You overwrite $retVal immediately. Maybe you meant:

      The objetc's method does return a string, I need a reference to that string, therefore I overwrite the variable with a reference to it's former value just to not need to declare another variable. I found it more readable than the following, which would work, too: $retVal = \$someObject->bar()->doSomething();

        But that way you lose the old value. I'm not sure that that's really what you want:

        #!perl -w use strict; use Data::Dumper; my $foo = 'bar'; $foo = \$foo; print $foo; print $$foo; print Dumper $foo; __END__ REF(0x12da554) REF(0x12da554) $VAR1 = \$VAR1;
Re: unreachable memory with a non-zero reference count
by hexcoder (Curate) on Jun 20, 2010 at 20:51 UTC
    In order to understand, lets see what happens

    { my $a; $a = \$a; # reference count of $a increases to 1 } # $a goes out of scope, but $a stays in use because of it +s reference count
    At the end the ref count of $a is not 0, so the memory is not freed. And since the referencer $a is not available anymore, the count can never be decreased to zero. We have a chunk of memory that has leaked.

    The problem is avoided, when we break the self reference manually at the end.

    my $a; $a = \$a; # reference count of $a increases to 1 undef $a; # reference count decreases to 0 } # $a goes out of scope, $a gets freed because of its refe +rence count of 0

    So regarding your question Is the problem that $a is declared in the block, but never assigned with something and never used elsewhere?

  • '$a declared in a block': Once $a goes out of scope it only gets freed, if its ref count is zero.
  • 'never assigned with something': No, here it is assigned with the reference to itself (which seems rather useless). This increases its own reference count to 1.
  • 'never used elsewhere': As long as you don't have circular references, it does not matter, how much it is used elsewhere.
  • In your code

    $retVal = $someObject->bar()->doSomething(); $retVal = \$retVal;
    you should use two variables, one for the value and one for the reference of the value.
    my $myVal = $someObject->bar()->doSomething(); $retVal = \$myVal;
    You don't have the problem of self-referencing then. In its current form it cannot work, because the variable can hold only one of the two things.

    The answer to your question Does this produces memory leaks like stated in the perl documentation? is yes, since there is nothing to break the circular self reference and thus leaves the ref count to 1.

Re: unreachable memory with a non-zero reference count
by JavaFan (Canon) on Jun 20, 2010 at 16:27 UTC
    Is the problem that $a is declared in the block, but never assigned with something and never used elsewhere?
    Considering half of two statements in the code fragment you quote assing to $a what makes you think it's never assigned with something?

    Perl uses refcounting to decide when to release memory. This check is done each time a scope is left. The idea is that if there's still a reference to a variable at scope exit, there's likely to be something outside the scope that still refers to the variable - and hence it must be kept. The code you quote is an example of where it may go wrong. Here, $a is assigned a reference. The reference it to itself. At that moment, the variable $a will have a refcount of 2 (its name, and the reference). When the scope is exited, the refcount drops to 1; its name is gone, but the reference still exists. So, $a is not marked as "memory to reuse". Yet $a cannot be referenced by any other code. This is considered a memory leak.

    Your code, OTOH, while not very useful, may, or may not, have a memory leak. It has the same issue as the quoted code, $retVal is a reference to itself. Why you first assign $someObject->bar()->doSomething(); to it, then discard the result is not clear to me. Nor is it clear to me what Log4perl->debug should do with its second argument. However, since you return $retVal, it's not a memory leak yet. $retVal's memory will not be marked "free for reuse" (because its refcount hasn't dropped to 0), but since you are returning the value of $retVal (which is a reference to $retVal), you can still reach it. If you discard the return value of foo, it's a memory leak. If you use it to break the circular reference, it's not.

      Why you first assign $someObject->bar()->doSomething(); to it, then discard the result is not clear to me. Nor is it clear to me what Log4perl->debug should do with its second argument.
      It just was an example, because I have methodes which work like that. doSomething() provides a string, but I need a reference to that string to send it to the calle of foo. I thought my line is more readable than $retVal = \$someObject->bar()->doSomething(); or user \$retVal wherever I want the reference. The second parameter to debug is only called when Log4perl actually logs something and used in the log message. The documentation of Log4perl prefers using anonymous subs with references to data when logging large strings because the strings won't be copied if the current log level is not debug.
        Your line may be more readable, it's not returning a reference to the string. It's returning a reference to itself.
        use 5.10.0; use strict; use warnings; sub foo {"A string"}; my $object = bless []; my $retVal1 = \$object->foo; my $retVal2 = $object->foo; $retVal2 = \$retVal2; say "$retVal1: $$retVal1"; say "$retVal2: $$retVal2"; say $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$retVal2; __END__ SCALAR(0x893c2c8): A string REF(0x894d1f4): REF(0x894d1f4) REF(0x8d9b1f4)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://845638]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2024-03-19 05:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found