sophate has asked for the wisdom of the Perl Monks concerning the following question:
Hi Monks,
In the script below, the lexical variable $lost is not visible to &test_sub2 which is what I expected. But I wonder why lexical variable $tricky is visible to &test_sub? How does Perl treat the lexical variables defined in the main script differently from those defined in a block?
Thanks in advance :-)
#!/usr/bin/perl
my $tricky = "in main";
&test_sub;
sub test_sub {
print "$tricky\n";
my $lost = "gone";
&test_sub2;
}
sub test_sub2 {
print "$lost\n";
}
The script above prints "in main".
Re: Scope of lexical variables in the main script
by GrandFather (Saint) on Apr 20, 2012 at 04:59 UTC
|
Perl doesn't treat lexical variables declared in the outer most block (at "file level") any different than lexical variables declared in a nested block. The scope for lexical variables is from their point of declaration to the end of the enclosing block. For file level variables that is to the end of the file.
Such variables are often known as global variables and should generally be avoided. It is common to use a run sub to ensure there are no unintentional global variables:
#!/usr/bin/perl
use strict;
use warnings;
run();
sub run {
my $tricky = "in run";
test_sub();
}
...
By the way using & to call subs is rather old school Perl style and probably isn't doing what you expect. Instead use the subname(); style shown above.
True laziness is hard work
| [reply] [d/l] [select] |
|
Thanks, got it :-)
One more question about lexical variables. If I define a lexical variable in a block, what happens to the memory storing the value of the lexical variable after the code exits the block?
For example, in the script below. I cannot directly access $tricky outside the block. But it can be done with a reference. My question is if the memory storing the contents of $tricky has been released right after the block ends? If so, does it mean some other programs can write to that memory and when I try to retrieve the value of $tricky with a reference after the block, I may get something unexpected(memory got overwritten by other program)?
#!/usr/bin/pere
my $reference;
{
my $tricky = "TRICKY";
$reference = \$tricky;
}
print "\$tricky is not defined\n" unless $tricky ;
# What happens to the memory storing the contents of $tricky?
# Has the memory storing $tricky been released?
print "Using a reference, here you are: $$reference\n";
| [reply] [d/l] |
|
Perl uses reference counting. In your case, inside the block,$tricky and $reference each own one reference to the scalar container that holds the string, "TRICKY". While inside the block, the reference count to the SV that holds the string "TRICKY" is two. After the block exits, $tricky goes out of scope, and the reference count drops by one, to one. As long as $reference remains in scope, the SV (the container for a scalar) holding the string "TRICKY" remains alive.
After $reference passes out of scope, assuming nobody else holds a reference to that scalar, the ref-count drops to zero. Perl regains that memory as available for future use. It's not released back to the OS.
Aren't you glad this isn't simple pointers in C or C++? :)
| [reply] [d/l] [select] |
|
Perl uses reference counting. Every time the code goes over a "my" variable, you are going to get new memory unless Perl can reuse what it had before (and it will it if it can - but Perl doesn't do garbage collection like JAVA).
If you pass a reference to that memory from the: my $trick = "TRICKY"; statement out of a sub, the next time Perl sees the "my", it allocates new memory for it if it sees that what it did before is still in "use" - meaning a reference to it exists. Perl "frees" memory back for its own use when it sees that the reference count to that memory is zero - not well illustrated in this example. The point here is that you get a completely new copy of "TRICKY" every time the sub is called.
My verbage was a bit confusing, but does the code answer the question?
#!/usr/bin/perl
use strict;
use warnings;
my @tricks;
for (1..3)
{
my $ref_to_a_trick = get_a_trick();
push @tricks, $ref_to_a_trick;
}
print @tricks,"\n"; #SCALAR(0x182b394)SCALAR(0x24920c)SCALAR(0x24925c)
#note each "trick reference" points to a different location
#@tricks is an array of scalar references
foreach my $ref (@tricks)
{
print "$$ref\n"; #de-reference each "trick" to get the value
#TRICKY
#TRICKY
#TRICKY
}
sub get_a_trick
{
my $trick = "TRICKY";
return (\$trick);
}
@tricks=(); will "free" the $tricks memory back to Perl (not to the O/S) and Perl will reuse it if it can because no references exists any longer to various memory allocations of "TRICKY". | [reply] [d/l] |
|
|
$tricky stays alive as long as there is a reference to it, all the way up until perl exits.
Here is another circular reference, a self-referential variable, it lives even after its inaccessible
{
my $TRICKIEST = "LEAK THAT LIVES FOREVER";
$TRICKIEST = \$TRICKIEST;
}
## its alive here, though there is no way to get to it
Well, you could use trickery like PadWalker to get at $TRICKIEST, but that is cheating :)
See Tutorials: Variable Scoping in Perl: the basics, Coping with Scoping
Mini-Tutorial: Perl's Memory Management
Memory leaks and circular references, Circular references and Garbage collection., make perl release memory | [reply] [d/l] |
|
| [reply] [d/l] |
Re: Scope of lexical variables in the main script
by AnomalousMonk (Archbishop) on Apr 20, 2012 at 19:33 UTC
|
The interleaving of the definition of 'global' variables (either lexical or package) with the invocation of functions that access them has yet another tricky aspect.
Variables are defined at compile time, but not initialized until run time (unless explicitly initialized in something like a BEGIN or INIT block or through some other compile-time mechanism such as the use built-in). This leads to situations in which a function can access a variable that has been created and exists (as proven by the fact that the code runs under strictures), but has no defined value. Invocation of the same function at a different point in the code will find the function accessing a defined value. All the more reason to be very circumspect about the use of global variables.
>perl -wMstrict -le
"func('before');
my $tricky = 'initialized at runtime';
func('after');
;;
sub func {
printf qq{$_[0]: %s defined: }, defined($tricky) ? 'is' : 'NOT';
print qq{'$tricky'};
}
"
Use of uninitialized value $tricky in concatenation (.) or string ...
before: NOT defined: ''
after: is defined: 'initialized at runtime'
| [reply] [d/l] [select] |
|
|