Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$h{k} ||= autovivifies differently from $h{k} = #9903

Open
p5pRT opened this issue Oct 8, 2009 · 4 comments
Open

$h{k} ||= autovivifies differently from $h{k} = #9903

p5pRT opened this issue Oct 8, 2009 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 8, 2009

Migrated from rt.perl.org#69666 (status was 'open')

Searchable as RT69666$

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2009

From andrew@pimlott.net

Created by andrew@pimlott.net

The following script

  my %h;
  eval { $h{k} = $h{k} || die };
  print exists $h{k} ? "key exists\n" : "key does not exist\n";
  eval { $h{k} ||= die };
  print exists $h{k} ? "key exists\n" : "key does not exist\n";

outputs

  key does not exist
  key exists

This defeats the purpose of the ||= for conditional assignment idiom. I
realize that the left side of ||= can only be evaluated once and then must
be used as both a value and an lvalue, but I can't see why this should
require creating the key.

Andrew

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.10.1:

Configured by Debian Project at Thu Oct  1 14:02:50 UTC 2009.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration:
   
  Platform:
    osname=linux, osvers=2.6.30.8-dsa-ia32, archname=i486-linux-gnu-thread-multi
    uname='linux murphy 2.6.30.8-dsa-ia32 #1 smp thu sep 24 23:51:44 cest 2009 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.10.1 -Dsitearch=/usr/local/lib/perl/5.10.1 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.10.1 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=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 -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.3.4', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /usr/lib64
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.9.so, so=so, useshrplib=true, libperl=libperl.so.5.10.1
    gnulibc_version='2.9'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.10.1:
    /home/andrew/lib/perl
    /home/andrew/local/lib/perl
    /etc/perl
    /usr/local/lib/perl/5.10.1
    /usr/local/share/perl/5.10.1
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.10
    /usr/share/perl/5.10
    /usr/local/lib/site_perl
    .


Environment for perl 5.10.1:
    HOME=/home/andrew
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=C
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/andrew/bin:/usr/sbin:/sbin:/home/andrew/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERL5LIB=/home/andrew/lib/perl:/home/andrew/local/lib/perl
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Oct 9, 2009

From @leonerd

On Thu, 08 Oct 2009 12​:18​:26 -0700
"andrew@​pimlott.net (via RT)" <perlbug-followup@​perl.org> wrote​:

The following script

my %h;
eval \{ $h\{k\} = $h\{k\} || die \};
print exists $h\{k\} ? "key exists\\n" : "key does not exist\\n";
eval \{ $h\{k\} ||= die \};
print exists $h\{k\} ? "key exists\\n" : "key does not exist\\n";

outputs

key does not exist
key exists

It may be of further interest to note that the following script

  my %h;
  eval { my $he = \$h{k}; $$he ||= die };
  print exists $h{k} ? "key exists\n" : "key does not exist\n";

outputs

  key exists

which more accurately depicts what the internals of the VM do under this
case.

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http​://www.leonerd.org.uk/

@p5pRT
Copy link
Author

p5pRT commented Oct 9, 2009

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Oct 9, 2009

From @davidnicol

here's a workaround using a nonautovivifying subroutine argument reference​:

perl -wle "sub S { $_[0] ||= die};eval {S $h{k}};print exists $h{k} ?
'E' : 'NE'"
NE

for a quick and backwards-compatible repair, you could make a

  sub TrueOrAssign($$){ $_[0] ||= $_[1] }

to replace the identified key leak in your program.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants