2014-12-13 14 views
4

У меня вопрос о том, когда и как переменные в подпрограмме освобождают память. Сценарий является примером:Переменные в подпрограммах Perl не освобождают память

#!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"; 
} 

и выходы на экране были:

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) 

я ожидал, что ссылки должны быть изменены, если подпрограмма А был назвать более чем один раз, но на выходе ссылки фиксировались независимо от того, когда вход был изменен или нет. Может ли явное явление, что память, занимаемая переменной в подпрограммах, никогда не может быть выпущена до тех пор, пока весь сценарий не закончится? В противном случае, мой результат необычен?

ответ

8
  1. Звонок A($i) выделяет новый массив в любом месте, где perl считает удобным доступным.
  2. Эта ссылка на массив возвращается в тело цикла и сохраняется в переменной, лексически привязанной к этому телу цикла.
  3. В нижней части цикла переменная выходит за пределы области видимости, и поскольку ничто иное не ссылается на этот массив, файл arrayref освобождается.
  4. Таким образом, что область памяти, которая ранее занимала ссылку на массив снова удобно доступна, и повторно используется, когда рядом необходимо ... в следующем вызове A()
  5. Гото 1

Если предотвратить массивы от получения вы увидите новые массивы, созданные по разным адресам.

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