On Variable Scope
This post contains a lightly edited reply of mine that was posted to the mt-dev mailing list over a year ago. I thought I would pull it from the archives and highlight it again since scope is an important concern of developers when developing code that will run in persistent FastCGI.
Mark Carey wrote:
What is the best way to "limit the scope" of variables? And while I think I know what objects and methods (subroutines/functions?), I am less clear about what are Classes and "class data" and how to deal with the scope issues there.
To which I responded:
Scoping is a bit of a broad topic. Hopefully this example should help with the basics though. Take this class (in Perl this is a package that conforms to a few object-oriented programming principles):
package Some::Class;my $class_data_persists;sub new { bless {}, $_[0] }sub set_object_data {my ($object,$val) = @_;$object->{value} = $val;}sub get_object_data {my ($object) = @_;return $object->{value}}sub set_class_data {my ($this,$val) = @_;$class_data_persists = $val;}sub get_class_data {return $class_data_persists}
In this example module (class) anything store in
$class_data_persists will be shared by any object of
Some::Class. So for instance.
use Some::Class;my $x = Some::Class->new; # creates an objectmy $y = Some::Class->new; # creates another object$x->set_class_data('hello world!');print $x->get_class_data; # prints hello world!print $y->get_class_data; # also prints hello world!
Notice that $x and $y are objects of class
Some::Class and that I stored the value 'hello world!' in
$x and yet $y knew about it to output it when
called. Since a persistent environment like FastCGI loads
Some::Class once and leaves it in memory the value 'hello
world!' will remain until the class is reloaded or overwritten with a new
value. This simple value is not damaging, however it can easily be abused
by storing large amount of data that consumes memory perhaps with data that
has become "stale" (its been updated in the database). The worst case is
when the class data keeps growing -- this is what is referred to as a
memory leak. As the application runs it eats up more and more memory until
the server comes to a crawl and finally crashes. This is a big issue in C
programming, but less so in scripting languages like Perl which clean up
memory that has gone out of scope. Perl still lets you leave variables and
data in some long term or persistent scope which is what we are discussing
here.
Back to our example to show some other types of scopes.
First I should note the $object variables in both
set_object_data and get_object_data. To Perl, these are two totally
different things despite having the same names. This is because each
instance has a scope of their respective methods. The first time one of
those methods is called, $object is set, the method continues
and finally completes. Once it completes $object goes "out of
scope" which means Perl removes it from its memory and frees up that space.
The second time the method is called it has no knowledge of the value of
the first $object or that it ever existed.
My example also has a type of scope which sits between the class and
method scopes I've discussed. In set_object_data I place that
value of $val in the object using
$object-{value}>. As long as the object exists the value will
remain in memory however that value is ONLY know to that object. For
example.
use Some::Class;my $x = Some::Class->new; # create an objectmy $y = Some::Class->new; # create another$x->set_object_data('hello world!');print $x->get_object_data; # prints hello world!print $y->get_object_data; # print undefined$y->set_object_data('foo');print $x->get_object_data; # still prints hello world!print $y->get_object_data; # prints foo
If $x and $y were in a method, like
$object and $val their value would be removed
from memory when that method finishes running and the object and any data
they contained along with it.
There are all types of ways you can screw up your scoping and
unintentionally leave something in memory. For instance, if the object
represented by $x above also gets stored in a class variable
elsewhere it won't be removed from memory when the method finishes running
because Perl knows it's (apparently) being used by the class and will keep
it in memory in case its needed. Memory isn't freed up until all its
references have gone out of scope.
Its a bit tricky to follow at first, but once you get the hang of it, it all becomes clear pretty quickly.
Hope that clarified some.

There are no comments yet. You could be the first!