weird bug

Discussion in 'Perl Misc' started by kj, Apr 18, 2008.

  1. kj

    kj Guest

    The following short module illustrates a puzzling bug:

    use strict;
    package Foo;
    my $x = +{ 1 => 'one' };

    sub foo {
    keys %$x if 0; # should do nothing
    my $y = eval '$x'; die if $@;
    printf "%d\n", scalar keys %$y;
    }

    1;
    __END__


    OK, now: the following one-liner produces the expected output:

    % perl -MFoo -e 'Foo::foo()'
    1

    ....but if one comments-out the first line of Foo::foo, the output changes:

    % perl -MFoo -e 'Foo::foo()'
    0

    Note that the line that was commented out should do nothing, because
    it ends with the conditional qualifier "if 0". Therefore, this
    line is essentially a no-op and should have absolutely no effect
    on the execution of this code.

    I'm seeing this behavior with v. 5.8.8. Does anyone see it also
    with more recent versions?

    I have no doubt that this is a bug, but I can't begin to figure
    out why it's happening. Any light that may be thrown on this puzzle
    would be much appreciated.

    Also, is there a better solution to this problem than including
    silly "voodoo code" like the first line in Foo::foo?

    TIA!

    Kynn

    --
    NOTE: In my address everything before the first period is backwards;
    and the last period, and everything after it, should be discarded.
    kj, Apr 18, 2008
    #1
    1. Advertising

  2. kj

    Guest

    kj <> wrote:
    > The following short module illustrates a puzzling bug:
    >
    > use strict;
    > package Foo;
    > my $x = +{ 1 => 'one' };
    >
    > sub foo {
    > keys %$x if 0; # should do nothing
    > my $y = eval '$x'; die if $@;
    > printf "%d\n", scalar keys %$y;
    > }
    >
    > 1;
    > __END__


    The appearance of $x in %$x causes the subroutine to take out and
    hold a "reference" to $x. The appearance of $x in the string eval
    doesn't cause that happen. I assume that when the __END__ is encountered,
    the "my $x" goes out of scope, decrementing the refcount. In the one
    case, the refcount is decremented to zero, and $x is freed. Later, when
    the string eval is invoked, it operates on this freed $x.


    > Also, is there a better solution to this problem than including
    > silly "voodoo code" like the first line in Foo::foo?


    Change
    my $y = eval '$x';
    to
    my $y = eval {$x};

    That way, the use of $x is not hidden from the subroutine so it knows to
    keep a reference to $x.

    Unless there is a good reason you were using '$x' instead of {$x} in the
    first place. I can't think of such a reason off the top of my head.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Apr 18, 2008
    #2
    1. Advertising

  3. kj

    Ben Morrow Guest

    Quoth kj <>:
    >
    > The following short module illustrates a puzzling bug:
    >
    > use strict;
    > package Foo;
    > my $x = +{ 1 => 'one' };
    >
    > sub foo {
    > keys %$x if 0; # should do nothing
    > my $y = eval '$x'; die if $@;
    > printf "%d\n", scalar keys %$y;
    > }
    >
    > 1;
    > __END__
    >
    >
    > OK, now: the following one-liner produces the expected output:
    >
    > % perl -MFoo -e 'Foo::foo()'
    > 1
    >
    > ...but if one comments-out the first line of Foo::foo, the output changes:
    >
    > % perl -MFoo -e 'Foo::foo()'
    > 0


    This can be reduced to

    package Foo;

    my $x = 1;

    sub foo {
    #$x;
    my $y = eval '$x';
    printf "from %s: %s\n",
    scalar caller, defined $y ? $y : '<undef>';
    }

    foo;

    1;

    which gives

    ~% perl -MFoo -eFoo::foo
    from Foo: 1
    from main: <undef>

    with all perls I have to hand (5.6, 5.8, 5.10, blead). This is a
    longstanding bug in eval STRING: it won't capture variables from an
    outer lexical scope unless they are explicitly mentioned in the
    immediately surrounding scope. Any mention, such as the line commented
    out, is sufficient.

    What I don't understand is 1. why it works when called from the same
    file and 2. I though this had been fixed in 5.10. I guess not...

    > Also, is there a better solution to this problem than including
    > silly "voodoo code" like the first line in Foo::foo?


    Fix perl's eval-handling to work properly? :)

    Ben
    Ben Morrow, Apr 18, 2008
    #3
  4. kj

    Guest

    Ben Morrow <> wrote:
    >
    > This can be reduced to
    >
    > package Foo;
    > my $x = 1;
    > sub foo {
    > #$x;
    > my $y = eval '$x';
    > printf "from %s: %s\n",
    > scalar caller, defined $y ? $y : '<undef>';
    > }
    > foo;
    > 1;
    >
    > which gives
    >
    > ~% perl -MFoo -eFoo::foo
    > from Foo: 1
    > from main: <undef>
    >
    > with all perls I have to hand (5.6, 5.8, 5.10, blead). This is a
    > longstanding bug in eval STRING: it won't capture variables from an
    > outer lexical scope unless they are explicitly mentioned in the
    > immediately surrounding scope. Any mention, such as the line commented
    > out, is sufficient.
    >
    > What I don't understand is 1. why it works when called from the same
    > file


    When it is called in the same file, the variable is still "in scope" in its
    own right because the file scope has not yet ended. Once the file
    scope has ended, the variable contents are destroyed unless something else
    (like a subroutine stuffed into the symbol table) keeps it alive.

    By replacing file-scope with extra curlies, you can get the same thing
    without using packages.

    perl -le ' {my $x=1; sub foo { print eval q{$x}}; foo; } foo;'

    I don't see how this could be fixed. Either you parse the eval string
    at compile time (which is not usually possible--if the string can't
    change between compile time and run time, why use string eval rather than
    block eval in the first place?), or you don't do garbage collection on any
    lexical variable which happens to be in scope when a string eval is
    encountered during the compilation pass. Or maybe when using a variable
    whose contents have already been freed should throw an error rather than
    treating it as undefined.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Apr 18, 2008
    #4
  5. kj

    Ben Morrow Guest

    Quoth :
    > Ben Morrow <> wrote:
    > >
    > > What I don't understand is 1. why it works when called from the same
    > > file

    >
    > When it is called in the same file, the variable is still "in scope" in its
    > own right because the file scope has not yet ended. Once the file
    > scope has ended, the variable contents are destroyed unless something else
    > (like a subroutine stuffed into the symbol table) keeps it alive.


    Yup. Thank you: I was confusing locating an entry in the lexical pad
    with refcounting of the contents of that entry.

    Ben
    Ben Morrow, Apr 18, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dorayme
    Replies:
    1
    Views:
    602
    richard
    Jan 21, 2011
  2. richard
    Replies:
    0
    Views:
    571
    richard
    Jan 21, 2011
  3. richard
    Replies:
    0
    Views:
    605
    richard
    Jan 21, 2011
  4. Beauregard T. Shagnasty

    Re: A Weird Appearance for a Weird Site

    Beauregard T. Shagnasty, Jan 21, 2011, in forum: HTML
    Replies:
    1
    Views:
    425
    Captain Paralytic
    Jan 21, 2011
  5. David Segall
    Replies:
    0
    Views:
    620
    David Segall
    Jan 22, 2011
Loading...

Share This Page