Re: Lost anonymous subs
by diotalevi (Canon) on Dec 09, 2004 at 15:15 UTC
|
A template copy of your code remains because it is used when creating the value to be assigned to $code. That template does not contain a copy of @arr. Also, the value of $code is GCed. Also, when $code was assigned, it didn't recieve a copy - it got a pointer to the current binding of @arr at the time. That pointer is also GCed and if the value in @arr has no more references, it also is GCed. In short, your code will behave itself. The now unused memory will be known to the perl interpreter as unused memory and it is now up to perl about whether it will return it to the operating system or not. I'm fuzzy on this but I recall others saying that some operating systems (like Windows) allow perl to return memory and perhaps others don't allow perl to return the memory. In any case, if you were to need that memory for other data in your program, it would be re-used for whatever that new use was.
| [reply] |
|
Thanks for information! Things got clearer. And what about closure behaviour? The sub WILL need a copy of @arr, won't it? I cannot understand what «a pointer to the current binding of @arr» is, pardon my ignorance, the term is not in perlref or perlsub :(
| [reply] [d/l] |
|
This is all perl internals, perlguts stuff. The CV you get in $code has an ->OUTSIDE C pointer to the PADLIST that @arr lives in and then the compiled code has a note on which index in that PADLIST it is suppposed to access the @arr at. So it isn't a copy. The code in $code works with the real, original @arr, not a copy.
| [reply] |
|
|
|
Re: Lost anonymous subs
by ikegami (Patriarch) on Dec 09, 2004 at 15:39 UTC
|
No, @arr is still accessible:
my @arr = (9) x 1000_000;
my $code = sub { @arr };
undef $code;
print(scalar(@arr), $/); # 1000000
You might mean
my $code;
{
my @arr = (9) x 1000_000;
$code = sub { @arr };
}
# @arr kept alive by the sub
undef $code;
# @arr freed
print(scalar(@arr), $/); # error under strict.
@arr would be freed at the undef. The memory is released to perl, but maybe not to the OS. There has been discussion on this in the past.
Nit: perl uses reference counting, not garbage collection.
| [reply] [d/l] [select] |
|
I have written almost exactly the same piece of code in the reply to diotalevi up there because did not spot your comment. Yes, that helped me to understand things.
I somehow got thinking that closures copy referenced lexicals when created. That was my error.
This is the case when copying really takes place:
my $Big = 'X' x 1000000;
sub big {
my $big = $Big;
return sub { $big };
}
my @crefs;
push @crefs, big() for 1..10;
| [reply] [d/l] |
|
Well yes, that's because the = operator copies stuff. There's nothing special about that.
| [reply] |
|
|
|
|
Not exactly copy, more just steal. Usually lexicals hang around for the next time they go into scope (though they get reset to be empty/undef, they still hold memory). If you take a reference to one (including the case of a closure) and hold the reference until the lexical goes out of scope, the lexical has to get reallocated, since the remaining reference keeps the original.
| [reply] |
|
Nit Nit: perl uses reference counting to see what can be safely garbage collected AFAIK.
| [reply] |
Re: Lost anonymous subs
by Joost (Canon) on Dec 09, 2004 at 17:54 UTC
|
Will it be garbage-collected? Anonymous subs cannot be GCed as far as I understand.
Unreferenced subroutines should be destroyed and garbage collected in perl (general caveats about circular references probably apply to subs too, I guess). IIRC there have been some problems in the past with memory leaks when removing subs (bugs in the perl interpreter: creating and destroying subs is valid and supported), so I just tested the following code in 5.8.5 and the process's memory use doesn't grow at all (it seems to be safe):
#!/usr/local/bin/perl -w
use strict;
while (1) {
my @arr = 'x' x 1000000;
my $subref = sub {
@arr;
}
}
| [reply] [d/l] |