Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 670
Ezekiel Kuo Avatar asked Feb 11 '23 09:02

Ezekiel Kuo


1 Answers

  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;
}
like image 180
pilcrow Avatar answered Feb 13 '23 21:02

pilcrow