On Fri, Sep 21, 2007 at 12:25:44PM +0100, Nicholas Clark
wrote:
> On Thu, Sep 20, 2007 at 03:22:47PM -0700, srezic cpan.
org wrote:
> > # New Ticket Created by srezic cpan.org
> > # Please include the string: [perl #45607]
> > # in the subject line of all future correspondence
about this issue.
> > # <URL: h
ttp://rt.perl.org/rt3/Ticket/Display.html?id=45607 >
> >
> >
> > This is a bug report for perl from srezic cpan.org,
> > generated with the help of perlbug 1.36 running
under perl 5.10.0.
> >
> >
> >
------------------------------------------------------------
-----
> > The following script generates a new warning in
perl5.10.0, but not
> > in perl5.8.8:
> >
> > Constant subroutine main::BLA redefined at
/usr/perl5.10.0d/lib/5.10.0/subs.pm line 36.
> >
> > Also, on exit there is a core dump
> >
> > #!perl
> > use constant BLA => "foo";
> > use subs qw(BLA);
>
> Mmm, that line probably shouldn't warn:
>
> sub import {
> my $callpack = caller;
> my $pack = shift;
> my imports = _;
> foreach $sym ( imports) {
> *{"$::$sym"} =
&{"$::$sym"};
> }
> };
>
> but thinking about the implementation, and what happens
when, it might be
> tricky to stop it from warning.
Fixing the bug fixed the warning. (change 31940). It's a
sutle corner case.
For the general case, what happens for *{"GLIPP"}
= &{"BONK"} is that the
peephole optimiser spots that construction, and adds flags
to two of the ops
to make the code lookup return a scalar reference if
possible, and the glob
assignment to assign that reference direct to the symbol
table if possible,
otherwise fix things up as if there had never been any
cheating:
The corner case is when $::BONK is a reference, and you
execute
*{"BONK"} = &{"BONK"}
Step 1: ops for &{"BONK"}; return us the
constant in the symbol table
Step 2: ops for *{"BONK"} cause that symbol table
entry (and our reference
to it) to be upgraded from RV to typeblob)
Step 3: We got to the code that attempted to assign the
reference into the
symbol table. A new reference needs to be created
and the referant
(the constant) pointed to it. (Rather than simply
bumping the
reference count of the existing reference, making a
new alias to it)
However, what has happened in step 2 is that the
reference placed on
the stack by step 1 has been converted to a
typeglob, which the old
code didn't realise could happen. So it still
merrily called SvRV() on
it to dereference it, and boom!
So now the code in step 3 is more robust, and handles the
case of the item
on the stack being changed from RV to PVGV.
Nicholas Clark
|