"Konovalov, Vadim" <[EMAIL PROTECTED]> writes: > > I'll try reducing a problem to a few lines, within this week. > > Actually CODE refs are destroyed too early in a quite simple scripts. Even > following code has a problem and gives error about unreferenced scalar and > "not a CODE reference": > > use strict; > > use Tcl::Tk; > my $int = new Tcl::Tk; > > $int->Eval(<<'EOS'); > pack [button .btn -text Go] > EOS > > my %wids; > > my $btn = $int->widget('.btn'); > $btn->configure(-command=>sub { > print STDERR "start processing...\n"; > print STDERR sort keys %wids, "\n"; > }); > > $int->MainLoop; > > > Interestingly, when I comment second "print" statement within anonymous sub, > error goes away: CODE destruction is not fast enough in this case.
Commenting out the print removes the reference to %wids which makes "sub {...}" just return a constant that lives in perl's OP-tree. It is only when there are references to outer lexicals that "sub {...}" returns a fresh CV each time it executes. Compare the output of these: perl -le 'my $a = 1; print map sub { $a }, 1..3' perl -le ' $a = 1; print map sub { $a }, 1..3' So without the reference to %wids the CV is kept alive because it lives in perl's OP-tree and everything is fine. With the %wids reference the sub only lives as long as the Tcl "perlsub" object keeps it alive. I added some prints to the "perlsub" destructor (FreePerlSub in Tcl.xs) and noticed that the sub is freed the first time the callback command executes. So what happens is that the button store the "perlsub" object just fine, but when the object is passed to Tcl_EvalObjEx() in TkInvokeButton() the first time then the object is mutated into a ByteCodeObj and at this point the CV reference is dropped. Too bad. Perhaps there is no hope for getting rid of %anon_refs and the current CV leakage. --Gisle