Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

STORE incorrectly invoked for local($_) on aliased tied array element #5268

Closed p5pRT closed 14 years ago

p5pRT commented 22 years ago

Migrated from rt.perl.org#8857 (status was 'resolved')

Searchable as RT8857$

p5pRT commented 22 years ago

From @mjdominus

Created by @mjdominus

I don't know if this is *the* bug from earlier this morning\, but I think it may be related\, and I don't think I can finish investigating the earlier problem until this is fixed.

The following program displays the bad behavior​:

  #!/usr/bin/perl

  $o = tie @​a\, 'T';

  for (@​a) {   k();   exit;   }

  sub k {   local $_;   }

  package T;

  sub TIEARRAY {   bless {} => "T";   }

  sub FETCH {   "r1\n";   }

  sub STORE {   my ($self\, $n\, $rec) = @​_;   unless (defined $rec) {   require Carp;   Carp​::confess("STORE($n\, undef) invoked. Why??");   }   return;   }

  sub FETCHSIZE { 1 }

Inside the loop\, we call k(). When k() tries to localize $_\, Perl calls STORE($object\, 0\, undef). It should not try to do this.

Perl Info ``` Flags: category=core severity=medium Site configuration information for perl v5.6.1: Configured by root at Sat Dec 29 11:54:59 EST 2001. Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=linux, osvers=2.4.2-2, archname=i586-linux uname='linux plover.com 2.4.2-2 #1 sun apr 8 19:37:14 edt 2001 i586 unknown ' config_args='-des' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler: cc='cc', ccflags ='-fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fno-strict-aliasing' ccversion='', gccversion='2.96 20000731 (Red Hat Linux 7.1 2.96-81)', 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, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lcrypt -lutil perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil libc=/lib/libc-2.2.2.so, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl v5.6.1: /usr/local/lib/perl5/5.6.1/i586-linux /usr/local/lib/perl5/5.6.1 /usr/local/lib/perl5/site_perl/5.6.1/i586-linux /usr/local/lib/perl5/site_perl/5.6.1 /usr/local/lib/perl5/site_perl/5.6.0/i586-linux /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl . Environment for perl v5.6.1: HOME=/home/mjd LANG=C LANGUAGE (unset) LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib LOGDIR (unset) PATH=/home/mjd/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/games:/sbin:/usr/sbin:/usr/local/bin/X11R6:/usr/local/bin/mh:/data/mysql/bin:/usr/local/bin/pbm:/usr/local/bin/ezmlm:/home/mjd/TPI/bin:/usr/local/teTeX/bin:/usr/local/mysql/bin PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

\mjd@​plover\.com writes​:

This is a bug report for perl from mjd@​plover.com\, generated with the help of perlbug 1.33 running under perl v5.6.1.

----------------------------------------------------------------- [Please enter your report here]

Inside the loop\, we call k(). When k() tries to localize $_\, Perl calls STORE($object\, 0\, undef). It should not try to do this.

{local $foo; }

translates (roughly) as perl pseudo-code​:

{ my $some_place_safe = $foo; $foo = undef; ... ... $foo = $some_place_safe; }

So if $foo is an alias to a tied thing I believe the STORE() is correct.

[Please do not change anything below this line] ----------------------------------------------------------------- --- Flags​: category=core severity=medium --- Site configuration information for perl v5.6.1​:

Configured by root at Sat Dec 29 11​:54​:59 EST 2001.

Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration​: Platform​: osname=linux\, osvers=2.4.2-2\, archname=i586-linux uname='linux plover.com 2.4.2-2 #1 sun apr 8 19​:37​:14 edt 2001 i586 unknown ' config_args='-des' hint=recommended\, useposix=true\, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler​: cc='cc'\, ccflags ='-fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\, optimize='-O2'\, cppflags='-fno-strict-aliasing' ccversion=''\, gccversion='2.96 20000731 (Red Hat Linux 7.1 2.96-81)'\, 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\, usemymalloc=n\, prototype=define Linker and Libraries​: ld='cc'\, ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lcrypt -lutil perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil libc=/lib/libc-2.2.2.so\, so=so\, useshrplib=false\, libperl=libperl.a Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-rdynamic' cccdlflags='-fpic'\, lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:

--- @​INC for perl v5.6.1​: /usr/local/lib/perl5/5.6.1/i586-linux /usr/local/lib/perl5/5.6.1 /usr/local/lib/perl5/site_perl/5.6.1/i586-linux /usr/local/lib/perl5/site_perl/5.6.1 /usr/local/lib/perl5/site_perl/5.6.0/i586-linux /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl .

--- Environment for perl v5.6.1​: HOME=/home/mjd LANG=C LANGUAGE (unset) LD_LIBRARY_PATH=/lib​:/usr/lib​:/usr/X11R6/lib LOGDIR (unset) PATH=/home/mjd/bin​:/usr/local/bin​:/bin​:/usr/bin​:/usr/X11R6/bin​:/usr/games​:/sbin​:/usr/sbin​:/usr/local/bin/X11R6​:/usr/local/bin/mh​:/data/mysql/bin​:/usr/local/bin/pbm​:/usr/local/bin/ezmlm​:/home/mjd/TPI/bin​:/usr/local/teTeX/bin​:/usr/local/mysql/bin PERL_BADLANG (unset) SHELL=/bin/bash -- Nick Ing-Simmons http​://www.ni-s.u-net.com/

p5pRT commented 22 years ago

From @mjdominus

Nick says​:

{local $foo; }

translates (roughly) as perl pseudo-code​:

{ my $some_place_safe = $foo; $foo = undef; ... ... $foo = $some_place_safe; }

I thought what it was supposed to do was to put the old SV on the save stack\, and then prepare a new\, fresh SV and associate it with the variable.

So if $foo is an alias to a tied thing I believe the STORE() is correct.

If that is the answer\, then it also implies that no tied array or hash method should use $_ under any circumstances\, and nor should any function that may ever be called by any tied array or hash method.

I can accept that\, but it seems like a rather extreme restriction.

It seems to me that p5p has already discussed this issue of localization of tied elements. It's not clear to me what is gained by having "local $_" call STORE(undef) and then STORE(oldvalue) later\, but if I can find the old discussion\, perhaps it will enlighten me.

p5pRT commented 22 years ago

From @vanstyn

Mark-Jason Dominus \mjd@​plover\.com wrote​: : :Nick says​: :> {local $foo; :> } :> :> translates (roughly) as perl pseudo-code​: :> :> { :> my $some_place_safe = $foo; :> $foo = undef; :> ... :> ... :> $foo = $some_place_safe; :> } : :I thought what it was supposed to do was to put the old SV on the save :stack\, and then prepare a new\, fresh SV and associate it with the :variable.

Well\, in principle we distinguish between cases where the magic is tied to the name (eg $!) and to the value (eg $a = $!). Is the problem here that tying acts as if it ties to the name? And if so\, is that something we can change without massive breakage? If not\, I think it would need at least a deprecation cycle.

Hugo

p5pRT commented 22 years ago

From @mjdominus

Well\, in principle we distinguish between cases where the magic is tied to the name (eg $!) and to the value (eg $a = $!). Is the problem here that tying acts as if it ties to the name?

No\, just the opposite. The problem is that tying acts as if it ties to the value.

In brief​:

1. @​a is tied.

2. $_ is temporarily aliased to $a[0].

3. Somewhere futher down the call stack\, "local $_" unexpectedly calls (tied @​a)->STORE(0\, undef).

And if so\, is that something we can change without massive breakage?

That\, I could not say. It's hard for me to imagine that anyone depends on "local $_" calling (tied @​a)->STORE(0\, undef) at the beginning of the block and (tied @​a)->STORE(0\, oldval) at the end\, but stranger things have happened.

p5pRT commented 22 years ago

From @abigail

On Tue\, Mar 19\, 2002 at 12​:01​:19PM -0500\, Mark-Jason Dominus wrote​:

Well\, in principle we distinguish between cases where the magic is tied to the name (eg $!) and to the value (eg $a = $!). Is the problem here that tying acts as if it ties to the name?

No\, just the opposite. The problem is that tying acts as if it ties to the value.

In brief​:

1. @​a is tied.

2. $_ is temporarily aliased to $a[0].

3. Somewhere futher down the call stack\, "local $_" unexpectedly calls (tied @​a)->STORE(0\, undef).

And if so\, is that something we can change without massive breakage?

That\, I could not say. It's hard for me to imagine that anyone depends on "local $_" calling (tied @​a)->STORE(0\, undef) at the beginning of the block and (tied @​a)->STORE(0\, oldval) at the end\, but stranger things have happened.

I've never written (serious) code that depends on this effect\, however\, the way it's acting now is what I expect will happen.

But perhaps I just have a twisted mind.

Abigail

p5pRT commented 22 years ago

From @schwern

On Tue\, Mar 19\, 2002 at 12​:01​:19PM -0500\, Mark-Jason Dominus wrote​:

That\, I could not say. It's hard for me to imagine that anyone depends on "local $_" calling (tied @​a)->STORE(0\, undef) at the beginning of the block and (tied @​a)->STORE(0\, oldval) at the end\, but stranger things have happened.

It has to work that way or else localizing tied variables doesn't work transparently.

I depend on it in File​::chdir. Not "local $_" specifically\, but "local $foo" and "local $foo[0]" to pull off end-of-scope actions.

schwern@​blackrider​:\~$ perl -wl   use File​::chdir;   use Cwd;   print cwd;   $CWD = '/usr/src';   print cwd;   {   local $CWD = '/tmp';   print cwd;   }   print cwd; /home/schwern /usr/src /tmp /usr/src

and there's an array version.

schwern@​blackrider​:\~$ perl -wl   use File​::chdir;   use Cwd;

  @​CWD = qw(usr local);   print cwd;   {   local $CWD[0] = 'var';   print cwd;   }   print cwd; /usr/local /var/local /usr/local

--

Michael G. Schwern \schwern@​pobox\.com http​://www.pobox.com/~schwern/ Perl Quality Assurance \perl\-qa@​perl\.org Kwalitee Is Job One flatulent no more\, I only make large bubbles of paste from my ass.   -- japhy

p5pRT commented 22 years ago

From @mjdominus

On Tue\, Mar 19\, 2002 at 12​:01​:19PM -0500\, Mark-Jason Dominus wrote​:

That\, I could not say. It's hard for me to imagine that anyone depends on "local $_" calling (tied @​a)->STORE(0\, undef) at the beginning of the block and (tied @​a)->STORE(0\, oldval) at the end\, but stranger things have happened.

It has to work that way or else localizing tied variables doesn't work transparently.

It doesn't have to work that way. In an earlier message\, Sarathy suggested that a better interface would be a LOCALIZE method​:

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-07/msg01916.html

In any case\, this is a tangent.

I depend on it in File​::chdir. Not "local $_" specifically\, but "local $foo" and "local $foo[0]" to pull off end-of-scope actions.

But that is exactly the point at issue. I am not really interested in what this​:

  local $foo[0]

should do; I can see the argument going either way. I am only complaining about this​:

  local $_

use File​::chdir;
use Cwd;

I'm afraid I don't see the relevance to the issue under discussion.

p5pRT commented 22 years ago

From @nwc10

(Andreas\, are you able to work out at which perl version the attached script started to SEGV? 5.6.0 does not SEGV\, 6850 does SEGV.)

On Tue\, Mar 19\, 2002 at 01​:09​:47PM -0500\, Mark-Jason Dominus wrote​:   Hugo (I think)​:   On Tue\, Mar 19\, 2002 at 12​:01​:19PM -0500\, Mark-Jason Dominus wrote​:

  > No\, just the opposite. The problem is that tying acts as if it ties   > to the value.   >   > In brief​:   >   > 1. @​a is tied.
  >   > 2. $_ is temporarily aliased to $a[0].   >   > 3. Somewhere futher down the call stack\, "local $_" unexpectedly calls   > (tied @​a)->STORE(0\, undef).

That\, I could not say. It's hard for me to imagine that anyone depends on "local $_" calling (tied @​a)->STORE(0\, undef) at the beginning of the block and (tied @​a)->STORE(0\, oldval) at the end\, but stranger things have happened.

It has to work that way or else localizing tied variables doesn't work transparently.

It doesn't have to work that way. In an earlier message\, Sarathy suggested that a better interface would be a LOCALIZE method​:

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-07/msg01916.html

In any case\, this is a tangent.

I depend on it in File​::chdir. Not "local $_" specifically\, but "local $foo" and "local $foo[0]" to pull off end-of-scope actions.

But that is exactly the point at issue. I am not really interested in what this​:

    local $foo\[0\]

should do; I can see the argument going either way. I am only complaining about this​:

    local $\_
use File​::chdir;
use Cwd;

I'm afraid I don't see the relevance to the issue under discussion.

I'm not sure if it does. But based on your original 1\,2\,3 should there be a difference between the 3 loops in?

sub bing {   local $_[0] = 'Bing'; }

foreach (@​a) {   bing ($_); }

foreach $a (@​a) {   bing ($a); }

foreach my $a (@​a) {   bing ($a); }

There is a difference​:

nick@​thinking-cap [nick]$ ~/test/tiearray.pl STORE Tie​::NewArray=ARRAY(0x8144150) 0 1 STORE Tie​::NewArray=ARRAY(0x8144150) 1 2 STORE Tie​::NewArray=ARRAY(0x8144150) 2 3 $_ FETCH Tie​::NewArray=ARRAY(0x8144150) 0 STORE Tie​::NewArray=ARRAY(0x8144150) 0 STORE Tie​::NewArray=ARRAY(0x8144150) 0 Bing

Attached is the test program.

5.005_03 behaves differently​:

perl5.00503 ~/test/tiearray.pl STORE Tie​::NewArray=ARRAY(0x8058f48) 0 1 STORE Tie​::NewArray=ARRAY(0x8058f48) 1 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 3 $_ FETCH Tie​::NewArray=ARRAY(0x8058f48) 0 STORE Tie​::NewArray=ARRAY(0x8058f48) 0 STORE Tie​::NewArray=ARRAY(0x8058f48) 0 Bing Attempt to free unreferenced scalar at /home/nick/test/tiearray.pl line 30. FETCH Tie​::NewArray=ARRAY(0x8058f48) 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 Bing $a FETCH Tie​::NewArray=ARRAY(0x8058f48) 0 STORE Tie​::NewArray=ARRAY(0x8058f48) 0 STORE Tie​::NewArray=ARRAY(0x8058f48) 0 Bing FETCH Tie​::NewArray=ARRAY(0x8058f48) 1 STORE Tie​::NewArray=ARRAY(0x8058f48) 1 STORE Tie​::NewArray=ARRAY(0x8058f48) 1 Bing FETCH Tie​::NewArray=ARRAY(0x8058f48) 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 Bing my $a FETCH Tie​::NewArray=ARRAY(0x8058f48) 0 STORE Tie​::NewArray=ARRAY(0x8058f48) 0 STORE Tie​::NewArray=ARRAY(0x8058f48) 0 Bing FETCH Tie​::NewArray=ARRAY(0x8058f48) 1 STORE Tie​::NewArray=ARRAY(0x8058f48) 1 STORE Tie​::NewArray=ARRAY(0x8058f48) 1 Bing FETCH Tie​::NewArray=ARRAY(0x8058f48) 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 STORE Tie​::NewArray=ARRAY(0x8058f48) 2 Bing

Hmm. So I can localise a lexical variable already if I try hard enough. For one definition of lexical.

5.6.0 doesn't have the Attempt to free unreferenced scalar warning. 5.6.1 and 6850 have the SEGV like 5.7.3

Nicholas Clark -- Even better than the real thing​: http​://nms-cgi.sourceforge.net/

p5pRT commented 22 years ago

From @nwc10

tiearray.pl

p5pRT commented 22 years ago

From @nwc10

D'oh! I forgot the most important line​:

Segmentation fault (core dumped)

I've put it in the correct place below too. It's also a 5.6.1 bug.

On Tue\, Mar 19\, 2002 at 07​:46​:54PM +0000\, Nicholas Clark wrote​:

(Andreas\, are you able to work out at which perl version the attached script started to SEGV? 5.6.0 does not SEGV\, 6850 does SEGV.)

There is a difference​:

nick@​thinking-cap [nick]$ ~/test/tiearray.pl STORE Tie​::NewArray=ARRAY(0x8144150) 0 1 STORE Tie​::NewArray=ARRAY(0x8144150) 1 2 STORE Tie​::NewArray=ARRAY(0x8144150) 2 3 $_ FETCH Tie​::NewArray=ARRAY(0x8144150) 0 STORE Tie​::NewArray=ARRAY(0x8144150) 0 STORE Tie​::NewArray=ARRAY(0x8144150) 0 Bing   Segmentation fault (core dumped)

Nicholas Clark -- Even better than the real thing​: http​://nms-cgi.sourceforge.net/

p5pRT commented 22 years ago

From @vanstyn

Mark-Jason Dominus \mjd@​plover\.com wrote​: : :> Well\, in principle we distinguish between cases where the magic is tied :> to the name (eg $!) and to the value (eg $a = $!). Is the problem here :> that tying acts as if it ties to the name? : :No\, just the opposite. The problem is that tying acts as if it ties :to the value.

Hmm\, I hadn't realised we were talking about tied aggregates\, but I disagree​: storing undef to an existing magic variable is the 'name' style localisation\, since we don't want to throw away the existing magic; replacing the current SV with a fresh one is the 'value' style.

Maybe\, then\, the problem is that our aliasing is too tight​: that C\<local $_> should break the connection between $_ and the variable it aliases (unlike C\<$_ = "foo">\, which we need lvaluable).

Hugo

p5pRT commented 22 years ago

From @andk

On Tue\, 19 Mar 2002 19​:46​:54 +0000\, Nicholas Clark \nick@&#8203;unfortu\.net said​:

  > (Andreas\, are you able to work out at which perl version the attached script   > started to SEGV? 5.6.0 does not SEGV\, 6850 does SEGV.)

Process is running. So much for now​: if you compiled 5.6.0 with -Dusethreads\, the coredump is even there. I'm now searching the threshold without threads. Is there any interest that I try threaded perls before 5.6.0?

-- andreas

p5pRT commented 22 years ago

From @mjdominus

1. I don't feel like I understand the possible issues here well enough to say for certain what should or should not be done.

2. My argument against the current behavior is exactly this​: Sometimes functions want to use $_. In the past\, this has sometimes caused strange action-at-a-distance effects. Usually\, people are advised that if they want to avoid strange action-at-a-distance\, they should localize $_ before using it. However\, it turns out that that advice is incorrect\, since the 'local' itself might cause an action-at-a-distance effect; it might even erase all your files. And there is absolutely no way to tell beforehand whether or not it will do this.

Whatever the right solution is\, I would hope that there would be a reasonable\, safe way for subroutines to use $_.

3. In the 'more wood on the fire' department\, I will point out that although this​:

  tie @​a\, 'T';   for (@​a) {   foo();   }

  sub foo {   local $_;   $_ = 12;   }

*does* call T​::STORE three times\, this​:

  tie @​a\, 'T';   for (@​a) {   foo();   }

  sub foo {   for (my $__dummy) {   $_ = 12;   }   }

does not call T​::STORE at all.

4. Although for (my $__dummy) { ... } is a safe way for a subroutine   to use $_\, I don't consider it reasonable.

5. There is another workaround​:

  local *_;

  *does* appear to be safe. Is this what we want to advise people to   do when they use $_? Should I prepare a doc patch?

Hoping that the answer is 'no'\,

-D.

p5pRT commented 22 years ago

From @rgarcia

On 2002.03.19 22​:35 Mark-Jason Dominus wrote​:

5. There is another workaround​:

    local \*\_; 

*does* appear to be safe. Is this what we want to advise people to do when they use $_? Should I prepare a doc patch?

Hoping that the answer is 'no'\,

Surely localizing *_ is a bad idea if you still want to use @​_.

p5pRT commented 22 years ago

From @andk

On Tue\, 19 Mar 2002 22​:02​:33 +0100\, andreas.koenig@​anima.de (Andreas J. Koenig) said​:

On Tue\, 19 Mar 2002 19​:46​:54 +0000\, Nicholas Clark \nick@&#8203;unfortu\.net said​: (Andreas\, are you able to work out at which perl version the attached script started to SEGV? 5.6.0 does not SEGV\, 6850 does SEGV.)

  > Process is running. So much for now​: if you compiled 5.6.0 with   > -Dusethreads\, the coredump is even there. I'm now searching the   > threshold without threads. Is there any interest that I try threaded   > perls before 5.6.0?

The patch you were looking for was 6214. And from there it was easy to grep to 4602 (pseudo-fork) which was between 5.005_62 and 5.005_63.

Good night/morning\, -- andreas

p5pRT commented 22 years ago

From @mjdominus

On 2002.03.19 22​:35 Mark-Jason Dominus wrote​:

5. There is another workaround​:

    local \*\_; 

*does* appear to be safe. Is this what we want to advise people to do when they use $_? Should I prepare a doc patch?

Hoping that the answer is 'no'\,

Surely localizing *_ is a bad idea if you still want to use @​_.

  sub defensive {   my (.....) = @​_;   local *_;   $_ = 'I LIKE PIE.';   ...;   }

It can be made to work. The existing advice\, to use 'local $_'\, cannot.

p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

Mark-Jason Dominus \mjd@&#8203;plover\.com writes​:

But that is exactly the point at issue. I am not really interested in what this​:

   local $foo\[0\]

should do; I can see the argument going either way. I am only complaining about this​:

   local $\_

No you are not you are complaining about what

  for (@​foo)   {   local $_;   }

does - in such a case $_ "is" (in some sense) $foo[0]

use File&#8203;::chdir;
use Cwd;

I'm afraid I don't see the relevance to the issue under discussion. -- Nick Ing-Simmons http​://www.ni-s.u-net.com/

p5pRT commented 22 years ago

From @mjdominus

You are complaining about what

for \(@&#8203;foo\)
 \{
  local $\_;
 \}

does

My real complaint is that it is impossible to use $_ safely in conjunction with tied variables.

This morning I went to write a doc patch for 'perltie'\, to say that

1. Use of $_ should be avoided in FETCH and STORE methods\, because these   might have been called from inside a for (@​tied) {} or
  for (values %tied) {} loop\, and

2. The usual solution of using "local $_"\, does not solve the problem   in this case.

But I did not send it in\, because it is not sufficient. $_ is not only unsafe in FETCH and STORE\, but also in any subroutine that might be called from FETCH or STORE.

in such a case $_ "is" (in some sense) $foo[0]

I think the sense in which $_ "is" $foo[0] should be weaker.

It appears that nobody except me is concerned by this\, so I'll let it drop.

p5pRT commented 22 years ago

From @nwc10

On Wed\, Mar 20\, 2002 at 09​:18​:17AM -0500\, Mark-Jason Dominus wrote​:

You are complaining about what

for \(@&#8203;foo\)
 \{
  local $\_;
 \}

does

My real complaint is that it is impossible to use $_ safely in conjunction with tied variables.

This morning I went to write a doc patch for 'perltie'\, to say that

1. Use of $_ should be avoided in FETCH and STORE methods\, because these might have been called from inside a for (@​tied) {} or
for (values %tied) {} loop\, and

2. The usual solution of using "local $_"\, does not solve the problem in this case.

But I did not send it in\, because it is not sufficient. $_ is not only unsafe in FETCH and STORE\, but also in any subroutine that might be called from FETCH or STORE.

in such a case $_ "is" (in some sense) $foo[0]

I think the sense in which $_ "is" $foo[0] should be weaker.

It appears that nobody except me is concerned by this\, so I'll let it drop.

I'd prefer not to have the action-at-a-distance of localising $_ I'm not sure how to make this consistent. I suspect it's as "simple" as localising anything that is aliasing something else (be it the argument of a for loop or a elements of @​_) should allocated new storage for what the *alias* points to\, and restore the original storage at scope end\, rather than the current behaviour.

(Which is reading the value and pushing it somewhere else\, writing a new value to the storage (triggering tie)\, and at scope end popping the old value and writing it)

But this is a language change\, and therefore ought to be subject to rule 1.

Nicholas Clark

p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

Mark-Jason Dominus \mjd@&#8203;plover\.com writes​:

You are complaining about what

for \(@&#8203;foo\)
 \{
  local $\_;
 \}

does

My real complaint is that it is impossible to use $_ safely in conjunction with tied variables.

This morning I went to write a doc patch for 'perltie'\, to say that

1. Use of $_ should be avoided in FETCH and STORE methods\, because these might have been called from inside a for (@​tied) {} or for (values %tied) {} loop\, and

2. The usual solution of using "local $_"\, does not solve the problem in this case.

But I did not send it in\, because it is not sufficient. $_ is not only unsafe in FETCH and STORE\, but also in any subroutine that might be called from FETCH or STORE.

in such a case $_ "is" (in some sense) $foo[0]

I think the sense in which $_ "is" $foo[0] should be weaker.

It appears that nobody except me is concerned by this\, so I'll let it drop.

I am concerned that local $_ and for (@​thing) donot treat $_ the same way. There is a principle of least surprise here which is being violated.

However in this particular case I think that $tied->STORE(0\,undef) is an entierly reasonable thing to do - and that if your FETCH/STORE are not able to cope with that they need re-writing.

-- Nick Ing-Simmons http​://www.ni-s.u-net.com/

p5pRT commented 22 years ago

From @nwc10

On Wed\, Mar 20\, 2002 at 06​:20​:52PM +0000\, Nick Ing-Simmons wrote​:

Mark-Jason Dominus \mjd@&#8203;plover\.com writes​:

You are complaining about what

in such a case $_ "is" (in some sense) $foo[0]

I think the sense in which $_ "is" $foo[0] should be weaker.

It appears that nobody except me is concerned by this\, so I'll let it drop.

I am concerned that local $_ and for (@​thing) do not treat $_ the same way. There is a principle of least surprise here which is being violated.

However in this particular case I think that $tied->STORE(0\,undef) is an entierly reasonable thing to do - and that if your FETCH/STORE are not able to cope with that they need re-writing.

I do not think it /entirely/ reasonable. Reasonable\, yes. But I feel it's also reasonable not to. There are two conflicting principles of least surprise here\, I feel​:

One is in favour of the existing behaviour\, by saying that local $anything does FETCH\, STORE and then STORE again at scope exit. And if $anything happens to be an alias into something tied\, or otherwise potentially explosive\, so be it. It is a logical result from several disjoint peices of documented behaviour.

The other says that local $anything should get you a local copy of $anything\, and that it is surprising that it has distant side effects for the case of $anything happening to be an alias to some other variable. Hence for the times when $anything is an implicit alias to something else\, then local locally makes it not.

I note that perlsyn.pod does say​:

  C\ probably won't do what you expect if VAR is a tied or other   special variable. Don't do that either.

It doesn't say to beware about LIST (or items in it) being tied.

I can't see that this is anything other than a language design issue\, so probably it belongs now on perl6-language. Or in an RFC about 2 years ago. I'll just warm up my time machine...

Nicholas Clark -- Even better than the real thing​: http​://nms-cgi.sourceforge.net/

p5pRT commented 22 years ago

From @timbunce

Could   local *_;

have a role to play here?

Tim.

On Wed\, Mar 20\, 2002 at 09​:18​:17AM -0500\, Mark-Jason Dominus wrote​:

You are complaining about what

for \(@&#8203;foo\)
 \{
  local $\_;
 \}

does

My real complaint is that it is impossible to use $_ safely in conjunction with tied variables.

This morning I went to write a doc patch for 'perltie'\, to say that

1. Use of $_ should be avoided in FETCH and STORE methods\, because these might have been called from inside a for (@​tied) {} or
for (values %tied) {} loop\, and

2. The usual solution of using "local $_"\, does not solve the problem in this case.

But I did not send it in\, because it is not sufficient. $_ is not only unsafe in FETCH and STORE\, but also in any subroutine that might be called from FETCH or STORE.

in such a case $_ "is" (in some sense) $foo[0]

I think the sense in which $_ "is" $foo[0] should be weaker.

It appears that nobody except me is concerned by this\, so I'll let it drop.

p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

Hello Mark-Jason!

MJD> My real complaint is that it is impossible to use $_ safely in MJD> conjunction with tied variables.

MJD> This morning I went to write a doc patch for 'perltie'\, to say that

MJD> 1. Use of $_ should be avoided in FETCH and STORE methods\, because these MJD> might have been called from inside a for (@​tied) {} or
MJD> for (values %tied) {} loop\, and

MJD> 2. The usual solution of using "local $_"\, does not solve the problem MJD> in this case.

MJD> But I did not send it in\, because it is not sufficient. $_ is not MJD> only unsafe in FETCH and STORE\, but also in any subroutine that might MJD> be called from FETCH or STORE.

NICK> in such a case $_ "is" (in some sense) $foo[0]

MJD> I think the sense in which $_ "is" $foo[0] should be weaker.

MJD> It appears that nobody except me is concerned by this\, so I'll let it drop.

Will you let me offer my word of encouragement? When I see something working unexpectedly (or buggy) in\, for example\, Perl\, I feel similar to seeing some injustice being committed. If I saw injustice in real life and feel that it will take me reasonable (well\, maybe moderate :-) effort to fix this injustice I would go ahead for it. Same here. When you or me see things behaving not as well as one could expect\, or at least not documented to behave badly (yes\, it is wouldn't be that bad if they were documented) we go for it - try to patch the implementation or docs. Everybody here does it this way :-)

To the problem​: \Amateur driving\ Hmm\, I've been thinking and got 3 ideas (that may play partially cooperatively or each of them alone)​:

1) $_ is very magical thing. Here it is one thing\, then another   what is the difference between local $a and local *a?   Only the difference that   1)   $b=\$a;   local $a;   #$$b is still the same as $a   2)   $b=\$a;   local *a;   #$$b is no longer same as $a

  (I leave aside the fact that local *a has an effect on %a\, @​a\, ...)

  But does doing \$_ make sense?   My idea #1 is to forbid \$_ (or not forbid :-) and to make   local $_; behave like local *_; but affecting only $_ and   not @​_ or anything else.

  That is crate a brand new scalar and assign it to *_{SCALAR}.  
  Does this make sense?

2) when any expression of the form $k is associated with   $a[i] or values %a via   for $k (@​a) or for $k(values %a)   and @​a or %a is tied just forbid localizing $k   (as well as $a[3] or $a{'a'})   Any good?

3) same as #2\, but instead of forbidding local $k   make local $k behave as local *k; but affecting only $k   and not %k\, @​k\,...   (#3 is same as #1 but not only $_ behaves this way\, but   any scalar $k being able to cause "action in a distance"   because of local $k.

  What do we loose with #3? The ability to do

  for $k (@​foo){   ...   $l = \$k;   ...   }

  and be sure that this $$l will still be equal to $k?

  But what does \$foo[3] mean if @​foo is tied? Is it   a reasonable operation?   If not\, then we loose exactly nothing when changing   behavior of local $k for $k being an alias to a   member of tied data structure.   BTW\, if \$foo[3] is useless for tied arrays it   should better be forbidden!

Oh\, well.. Mark\, if nothing of this is any good (I'm a novice :-) and if you don't find a way out yourself\,..well it would be at least terribly nice to have the docs patched!

My heartiest regards\, Anton

p5pRT commented 14 years ago

From @iabyn

(closing an old ticket). There are two issues in this ticket​: the OP's\, whereby $_ may remain tied after local($_); and the second\, which Nicholas discovered while working on the OPs code\, that turned up a premature free. The latter has now been fixed by commit 459defa14829d1e98582a2fcd871ef3425e1fe38 in branch davem/post-5.12\, which should be merged back into blead once 5.12 has been released\, and thus appear in 5.13 onwards.

As for the original issue\, this is essentially unfixable\, but instead we now have lexical C\<my $_> which obviates the need for C\<local $_>.

As to why its unfixable\, it's really the conjunction of two expectations\, neither of which we can change. First\, we expect   n=FETCH() / STORE(n+1) to be called for each element in the following​:

  $_ += 1 for (@​tied);

Second\, we expect a tied element to remain tied within the local's scope​:

  {   local $tied[0] = 1;   $x = $tied[0] + 1; # calls FETCH   }

Put these two together\, and you get

  for (@​tied) {   local $_ = 1;   $x = $_ + 1; # calls FETCH   }

p5pRT commented 14 years ago

@iabyn - Status changed from 'open' to 'resolved'