develooper Front page | perl.perl5.porters | Postings from April 2011

[perl #89544] closure keeps containing scope alive

Thread Next
From:
perlbug @ plan9 . de
Date:
April 29, 2011 02:24
Subject:
[perl #89544] closure keeps containing scope alive
Message ID:
rt-3.6.HEAD-32285-1304060236-1887.89544-75-0@perl.org
# New Ticket Created by  perlbug@plan9.de 
# Please include the string:  [perl #89544]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=89544 >



This is a bug report for perl from perlbug@plan9.de,
generated with the help of perlbug 1.39 running under perl 5.12.3.


-----------------------------------------------------------------
[Please describe your issue here]

The following code creates three nested closures. outer2 creates an object
and stores it in my $a. the nested sub outer references it and creates a
third closure inner, which references a variable from the outer closure.

Then it calls outer2 which calls outer. After it returns, the expectation
is that $outer is destroyed, including all local variables that are no
longer referenced ($a), but this is not the case, as the inner closure
keeps the outer alive, including (apparently) all its local variables.

Or in other words, $inner keeps the variable $a alive, even though it is
not referencing it.

Expected outcome would be (a gets destroyed when outer and outer2 get
destroyed:

   destroyed
   a should be destroyed now

Actual behaviour:

   a should be destroyed now
   destroyed

While one could argue that a closure keeps the containing scope alive,
perl doesn't do that in most cases (see second example), so the behaviour
is not consistent (either it keeps all variabels alive or none of them).

I have reported almost the same bug in the past, but this one is
different.

   #!/opt/bin/perl

   sub warner::DESTROY {
       warn "destroyed\n";
   }

   my $outer2 = sub {
       my $a = bless \my $dummy, warner::;

       my $outer = sub {
           my $b;
           my $inner = sub {
               undef $b;
           };

           $a;

           $inner
       };

       $outer->()
   };

   my $inner = $outer2->();
   warn "a should be destroyed now\n";

Second example, here a gets destroyed as expected, even though the closure
references other variables from the containing scope.

   sub warner::DESTROY {
       warn "destroyed\n";
   }

   my $outer = sub {
       my $a = bless \my $dummy, warner::;
       my $b;
       my $inner = sub {
           undef $b;
       };

       $inner
   };

   my $inner = $outer->();
   warn "a should be destroyed now\n";


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=low
---
Site configuration information for perl 5.12.3:

Configured by Marc Lehmann at Wed Feb 23 06:21:02 CET 2011.

Summary of my perl5 (revision 5 version 12 subversion 3) configuration:
   
  Platform:
    osname=linux, osvers=2.6.32-5-amd64, archname=x86_64-linux
    uname='linux cerebro 2.6.32-5-amd64 #1 smp wed jan 12 03:40:32 utc 2011 x86_64 gnulinux '
    config_args='-Duselargefiles -Duse64bitint -Dusemymalloc=n -Dstatic_ext=Fcntl -Dcc=gcc -Dccflags=-DPERL_DISABLE_PMC -DPERL_ARENA_SIZE=16376 -USITEARCH_EXP -USITELIB_EXP -UARCHLIB_EXP -D_GNU_SOURCE  -I/opt/include -ggdb -gdwarf-2 -g3 -Doptimize=-O6 -fno-strict-aliasing -Dcccdlflags=-fPIC -Dldflags=-L/opt/perl/lib -L/opt/lib -Dlibs=-ldl -lm -lcrypt -lgdbm -Dprefix=/opt/perl -Dprivlib=/opt/perl/lib/perl5 -Darchlib=/opt/perl/lib/perl5 -Uusevendorprefix -Dsiteprefix=/opt/perl -Dsitelib=/opt/perl/lib/perl5 -Dsitearch=/opt/perl/lib/perl5 -Dsitebin=/opt/perl/bin -Dman1dir=/opt/perl/man/man1 -Dman3dir=/opt/perl/man/man3 -Dsiteman1dir=/opt/perl/man/man1 -Dsiteman3dir=/opt/perl/man/man3 -Dman1ext=1 -Dman3ext=3 -Dpager=/usr/bin/less -Uafs -Uusesfio -Uusenm -Uuseshrplib -Ud_dosuid -Dusethreads=undef -Duse5005threads=undef -Duseithreads=undef -Dusemultiplicity=undef -Demail=perl-binary@plan9.de -Dcf_email=perl-binary@plan9.de -Dcf_by=Marc Lehmann -Dlocincpth=/opt/perl/include /opt/incl
 ude -Dmyhostname=localhost -Dmultiarch=undef -Dbin=/opt/perl/bin -Dxxxusedevel -DxxxDEBUGGING -Dxxxuse_debugging_perl -Dxxxuse_debugmalloc -dEs'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-DPERL_DISABLE_PMC -DPERL_ARENA_SIZE=16376 -USITEARCH_EXP -USITELIB_EXP -UARCHLIB_EXP -D_GNU_SOURCE -I/opt/include -ggdb -gdwarf-2 -g3 -fno-strict-aliasing -pipe -I/opt/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O6 -fno-strict-aliasing',
    cppflags='-DPERL_DISABLE_PMC -DPERL_ARENA_SIZE=16376 -USITEARCH_EXP -USITELIB_EXP -UARCHLIB_EXP -D_GNU_SOURCE -I/opt/include -ggdb -gdwarf-2 -g3 -fno-strict-aliasing -pipe -I/opt/include'
    ccversion='', gccversion='4.4.5', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags ='-L/opt/perl/lib -L/opt/lib -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-ldl -lm -lcrypt -lgdbm
    perllibs=-ldl -lm -lcrypt
    libc=/lib/libc-2.11.2.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.11.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O6 -fno-strict-aliasing -L/opt/perl/lib -L/opt/lib -L/usr/local/lib'

Locally applied patches:
    

---
@INC for perl 5.12.3:
    /root/src/sex
    /opt/perl/lib/perl5
    /opt/perl/lib/perl5
    .

---
Environment for perl 5.12.3:
    HOME=/root
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/root/s2:/root/s:/opt/bin:/opt/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11/bin:/usr/games:/usr/local/bin:/usr/local/sbin:/root/pserv:.
    PERL5LIB=/root/src/sex
    PERL5_CPANPLUS_CONFIG=/root/.cpanplus/config
    PERLDB_OPTS=ornaments=0
    PERL_ANYEVENT_DBI_TESTS=1
    PERL_ANYEVENT_EDNS0=1
    PERL_ANYEVENT_NET_TESTS=1
    PERL_ANYEVENT_PROTOCOLS=ipv4,ipv6
    PERL_ANYEVENT_STRICT=1
    PERL_BADLANG (unset)
    PERL_UNICODE=E
    SHELL=/bin/bash


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About