Talk:Using transactions
From ClassDBI
13 Nov 2006
Edward Sabol: Please prove that closures referencing external variables will leak because I think what you say is misleading and I've got a test script below to test the theory. The only way closures leak memory afaik is when you assign a sub {} to a scalar and then let it call itself recursively as such:
my $leaky;
$leaky = sub {
my $count = shift;
if ($count > 0) {
&$leaky($count - 1);
}
};
&$leaky(10);
See this test script (requires Devel::Leak):
#!/usr/local/bin/perl -w
use strict;
use Devel::Leak;
my $handle;
my $count;
my $new_count;
print "Test 1 (circular refs). This will leak.\n";
$count = Devel::Leak::NoteSV($handle);
print "\tPre count: $count\n";
&test_circ_refs();
$new_count = Devel::Leak::NoteSV($handle);
print "\tPost count: $new_count\n";
print "Test 2 (self-referencing closure). This will leak.\n";
$count = Devel::Leak::NoteSV($handle);
print "\tPre count: $count\n";
&test_closure_self_ref(10);
$new_count = Devel::Leak::NoteSV($handle);
print "\tPost count: $new_count\n";
print "Test 3 (closure referencing external vars). This won't leak.\n";
$count = Devel::Leak::NoteSV($handle);
print "\tPre count: $count\n";
&test_closure_ext_ref(10);
$new_count = Devel::Leak::NoteSV($handle);
print "\tPost count: $new_count\n";
sub test_circ_refs {
my $a;
my $b = \$a;
$a = \$b;
}
sub test_closure_self_ref {
my $count = shift;
my $code;
$code = sub {
my $count = shift;
print "\t\trecursion: $count\n";
if ($count > 0) {
&$code($count - 1);
}
};
&$code($count);
}
sub test_closure_ext_ref {
my $count = shift;
while ($count > 0) {
&{sub { my $foo = $count; $count--; print "\t\trecursion: $count\n"; }}();
}
}
-- cmanley
I suppose the only evidence I have handy at the moment is anecdotal, often experienced when using Error.pm's try/catch syntax in mod_perl applications. I will defer to your mad Devel::Leak skillz, however, and change the text accordingly to indicate that closures may occur.
-- EdwardSabol 17:52, 15 November 2006 (GMT)

