Ezekiel Kuo
Ezekiel Kuo

Reputation: 155

Variables in Perl subroutines do not release the memories

I have a question about when and how variables in a subroutine release the memory. The script is an example:

#!perl/bin/per
use strict;
sub A{
    my $x= shift;
    return ([$x]);
}
for my $i (1..10){
    my $ref= &A($i);## the input changes in each round
    my $ref2= &A(9);## the input is fixed in each round
    print "$ref\t";
    print "$ref2\n";
}

and the outputs on the screen were:

ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)
ARRAY(0x996e98) ARRAY(0x9b50c8)

I expected that the references should be changed when the subroutine A was called more than one time, but the output references were fixed no matter when the input was changed or not. Can the phenomenon infers that the memories occupied by variable in a subroutines can never be released until the whole script is over? Otherwise, is my result unusual?

Upvotes: 4

Views: 159

Answers (1)

pilcrow
pilcrow

Reputation: 58589

  1. A call to A($i) allocates a new arrayref at whatever location perl thinks is conveniently available.
  2. That array reference is returned to your loop body, and stored in a variable lexically scoped to that loop body.
  3. At the bottom of the loop, the variable goes out of scope, and as nothing else references that arrayref, the arrayref is deallocated.
  4. Thus that memory location which formerly held the arrayref is again conveniently available, and is reused when next needed ... at the next call to A()
  5. goto 1

If you prevent the arrays from getting freed, you'll see the new arrays being created at different addresses.

my @a;
for my $i (1..10){
    my $ref= &A($i);## the input changes in each round
    my $ref2= &A(9);## the input is fixed in each round
    print "$ref\t";
    print "$ref2\n";
    push @a, $ref, $ref2;
}

Upvotes: 8

Related Questions