bcrowell2 has asked for the wisdom of the Perl Monks concerning the following question:

I have a program that worked fine in Perl 5.6, but fails in 5.8. I'd appreciate any suggestions on how to fix it. The following is a minimal example that produces the failure:
BEGIN { my %x = (); }
This little program runs fine in perl 5.6.1, but here's what I get in 5.8.4:
$ perl test.pl Bizarre copy of HASH in leavesub at test.pl line 3. BEGIN failed--compilation aborted at test.pl line 3.
TIA!

Replies are listed 'Best First'.
Re: upgrade to 5.8.4 breaks code -- how to fix?
by Corion (Patriarch) on Jun 05, 2004 at 16:12 UTC

    I can confirm this for Perl 5.8.4, compiled from source for Debian Linux:

    perl5.8.4 -we 'BEGIN{my %x=()}'

    produces

    Bizarre copy of HASH in leavesub at -e line 1. BEGIN failed--compilation aborted at -e line 1.

    It seems that it is necessary that %x is a lexical variable local to the BEGIN block. The following other variants produce no error:

    perl5.8.4 -we '{my %x=()}' perl5.8.4 -we 'my %x=()' perl5.8.4 -we 'BEGIN{ %x=()}' Name "main::x" used only once: possible typo at -e line 1. perl5.8.4 -we 'my%x;BEGIN{ %x=()}' perl5.8.4 -we 'my%x;BEGIN{ {%x=()}}'

    This seems to indicate that a possible workaround would be to move the lexical declaration out of the BEGIN block, but into an inner block, so that it gets cleared after the program has started running:

    perl5.8.4 -we '{my%x;BEGIN{ {%x=()}}}'

    Deparse produces the non-initializing code for the oneliner, so I guess that davido is correct with his diagnosis that the optimization causes this error:

    perl5.8.4 -w -MO=Deparse -e 'BEGIN{ my %x=()}' Bizarre copy of HASH in leavesub at -e line 1. BEGIN failed--compilation aborted at -e line 1. BEGIN { $^W = 1; } sub BEGIN { my %x; }

    My Perl has the following characteristics:

    corion@aliens:~$ perl5.8.4 -V Summary of my perl5 (revision 5 version 8 subversion 4) configuration: Platform: osname=linux, osvers=2.4.25, archname=i686-linux-thread-multi uname='linux aliens 2.4.25 #2 sun feb 22 12:12:48 cet 2004 i686 un +known ' config_args='-Dinc_version_list=none -Dprefix=/opt/perl' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemulti +plicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS +-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE +_OFFSET_BITS=64', optimize='-O3', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-stri +ct-aliasing -I/usr/local/include' ccversion='', gccversion='2.95.4 20011002 (Debian prerelease)', gc +cosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=/lib/libc-2.2.5.so, so=so, useshrplib=false, libperl=libperl. +a gnulibc_version='2.2.5' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL +_IMPLICIT_CONTEXT Built under linux Compiled at May 8 2004 09:58:09 @INC: /opt/perl/lib/5.8.4/i686-linux-thread-multi /opt/perl/lib/5.8.4 /opt/perl/lib/site_perl/5.8.4/i686-linux-thread-multi /opt/perl/lib/site_perl/5.8.4 /opt/perl/lib/site_perl .

      Does this bug hold with a perl 5.8.4 that is not compiled for threads (or multiplicity)? I'm just curious.

        Does this bug hold with a perl 5.8.4 that is not compiled for threads
        It's in all versions of 5.8.4. It occurs whenever my %h=() or my @a=() is used in a place that's expected to to return a list, such as the last statement in a function called in list contect, or more unlikely, @a=(my @b=()). The optimisation to get rid of the =() accidently makes the expression return the array or hash itself rather than a list of it's contents. Thus leading to the 'bizarre copy of hash' error.

        Dave.

Re: upgrade to 5.8.4 breaks code -- how to fix?
by dave_the_m (Monsignor) on Jun 05, 2004 at 18:44 UTC
    It's already been fixed for the forthcoming 5.8.5 release.

    Dave.

Re: upgrade to 5.8.4 breaks code -- how to fix?
by davido (Cardinal) on Jun 05, 2004 at 16:03 UTC
    Funny, with Perl 5.8.3, the following doesn't generate any kind of error (nor should it):

    perl -e 'BEGIN { my %x = (); }'

    And in reading perldelta for version 5.8.4, the only change to how   my %x = (); is handled is that the unnecessary initialization to the empty set is optimized away, which also shouldn't cause any errors.

    Are you sure that those three lines, by themselves, generate the error you've described? I don't have 5.8.4 installed anywhere to confirm, but unless there's a bug in Perl, the code you presented should be just fine.

    UPDATE: Ok, now that corion has confirmed it (and yes, I think it has to be related to the new optimization), who's going to submit the bug report? This code shouldn't generate an error, it's legitimate code.


    Dave

      Thanks, davido and Corion, for the help! Corion's workaround does indeed fix the problem for me. I'd be interested in having the experience of reporting the bug, but what's the correct way to do it -- dash off an e-mail to Larry Wall, or is there a bugzilla or a mailing list or something? Corion clearly has more Perl-fu than I do, so if Corion wants to handle the bug report instead of me, that's fine too.

        The proper way to go about reporting a bug (possibly after having verified it with other people, as you did) is to run perlbug, and type/paste in your bug report. Note that I didn't check http://rt.perl.org/perlbug/ for a possible duplicate, so your bug report might duplicate some already existing open bug report.

        So, in your case, do that, paste in your snippet, or better the oneliner snippet I used, add some description of what you expected to happen, and what happened, and add the link to the root node here for further reference.

        perlbug will then send a mail to the perl5-porters mailing list in your name, and a bug ticket on http://rt.perl.org/perlbug/ will also be created automagically.

        If all goes well, you'll either hear back directly from somebody who fixed your bug or you'll find it fixed in Perl 5.8.6 ...