Modification of a read-only value attempted - why?

Discussion in 'Perl Misc' started by Tony Lawrence, Sep 15, 2006.

  1. Can someone explain this to me?

    (full text at http://aplawrence.com/Unix/perl_readonly.html ,
    abbreviated version here)

    Test code:

    #!/usr/bin/perl -w
    # no problem here
    caroomba("first");


    @dayval=qw(foo ba);
    foreach $dayval (@dayval) {
    # no problem here
    caroomba($dayval);
    }


    foreach $dayval ("foo2","ba2") {
    # no problem here either
    caroomba($dayval);
    }


    foreach ("foo3","ba3") {
    # doesn't like this
    $dayval=$_;
    caroomba($dayval);
    }



    sub caroomba {
    my $p=shift;
    print "Caroomba called $p\n";
    open(I,"./t");
    while (<I>) {
    # stuff..
    }
    close I;
    }


    When run, that produces:


    Caroomba called first
    Caroomba called foo
    Caroomba called ba
    Caroomba called foo2
    Caroomba called ba2
    Caroomba called foo3 Modification of a read-only value attempted at
    ../t.pl line 23, <I> line 23.

    Why?

    Something to do with anonymous arrays, but I don't grok it.
     
    Tony Lawrence, Sep 15, 2006
    #1
    1. Advertising

  2. Tony Lawrence wrote:
    > Can someone explain this to me?
    >
    > (full text at http://aplawrence.com/Unix/perl_readonly.html ,
    > abbreviated version here)
    >
    > Test code:


    [still rather long ]

    I've abberviated your example to:

    for ("foo3") {
    while (<DATA>) {
    }
    }
    __END__

    The <> construct in a while() performs an implicit assignment to the
    global variable $_ but does _not_ perform an implicit local($_) in the
    way for() does.

    The for() makes the global variable $_ an alias for the readonly value
    "foo3".

    > Something to do with anonymous arrays, but I don't grok it.


    No, nothing to do with arrays.

    The obvious, but _wrong_ solution is to insert local($_) before the
    while(<...>). This will work 99.99% of the time but that last time in
    10000 $_ will be aliased to an element of a tied agregate (HASH or
    ARRAY) and then local($_) will do evil things.

    The correct fix is either to local(*_) or to avoid the implicit
    assignment feature completely.

    Note that an unfortunate side effect of local(*_) is that is localizes
    @_ etc too. You can get arround this with the rather peverse looking
    code...

    local(*_) = do{ \my $underscore };
     
    Brian McCauley, Sep 15, 2006
    #2
    1. Advertising

  3. Tony  Lawrence

    -berlin.de Guest

    Tony Lawrence <> wrote in comp.lang.perl.misc:
    > Can someone explain this to me?
    >
    > (full text at http://aplawrence.com/Unix/perl_readonly.html ,
    > abbreviated version here)
    >
    > Test code:


    [snip code that doesn't show the problem]

    > foreach ("foo3","ba3") {
    > # doesn't like this
    > $dayval=$_;
    > caroomba($dayval);
    > }
    >
    >
    >
    > sub caroomba {
    > my $p=shift;
    > print "Caroomba called $p\n";
    > open(I,"./t");
    > while (<I>) {
    > # stuff..
    > }
    > close I;
    > }
    >
    >
    > Caroomba called foo3 Modification of a read-only value attempted at
    > ./t.pl line 23, <I> line 23.
    >
    > Why?
    >
    > Something to do with anonymous arrays, but I don't grok it.


    Which anonymous array? I don't see any.

    The problem is the nesting (through a sub call) of the outer
    for-loop and the inner while-loop. The outer "for" aliases $_
    to the read-only literal "foo3". This alias is still in effect
    inside the sub. The while-loop now tries to use the variable
    $_ as its implicit variable. Since $_ is aliased to a read-only
    value, that fails with the error you see.

    Anno
     
    -berlin.de, Sep 15, 2006
    #3
  4. -berlin.de wrote:
    > Tony Lawrence <> wrote in comp.lang.perl.misc:
    > > Can someone explain this to me?
    > >
    > > (full text at http://aplawrence.com/Unix/perl_readonly.html ,
    > > abbreviated version here)
    > >
    > > Test code:

    >
    > [snip code that doesn't show the problem]
    >
    > > foreach ("foo3","ba3") {
    > > # doesn't like this
    > > $dayval=$_;
    > > caroomba($dayval);
    > > }
    > >
    > >
    > >
    > > sub caroomba {
    > > my $p=shift;
    > > print "Caroomba called $p\n";
    > > open(I,"./t");
    > > while (<I>) {
    > > # stuff..
    > > }
    > > close I;
    > > }
    > >
    > >
    > > Caroomba called foo3 Modification of a read-only value attempted at
    > > ./t.pl line 23, <I> line 23.
    > >
    > > Why?
    > >
    > > Something to do with anonymous arrays, but I don't grok it.

    >
    > Which anonymous array? I don't see any.
    >
    > The problem is the nesting (through a sub call) of the outer
    > for-loop and the inner while-loop. The outer "for" aliases $_
    > to the read-only literal "foo3". This alias is still in effect
    > inside the sub. The while-loop now tries to use the variable
    > $_ as its implicit variable. Since $_ is aliased to a read-only
    > value, that fails with the error you see.
    >
    > Anno


    OK, I see it now. If the subroutine is modified to add

    print "\$_ is $_\n";

    it shows up quickly:

    ...
    Use of uninitialized value in concatenation (.) or string at ./t.pl
    line 21.
    $_ is
    Caroomba called ba2
    $_ is foo3
    Caroomba called foo3
    Modification of a read-only value attempted at ./t.pl line 24.

    I never realized that $_ would be passed down to a subroutine.. I
    thought the sub would have its own $_.. but there it is.

    So.. this isn't considered a bug or flaw in Perl? This is intended
    behavior?
     
    Tony Lawrence, Sep 16, 2006
    #4
  5. Tony  Lawrence

    -berlin.de Guest

    Tony Lawrence <> wrote in comp.lang.perl.misc:
    >
    > -berlin.de wrote:
    > > Tony Lawrence <> wrote in comp.lang.perl.misc:
    > > > Can someone explain this to me?
    > > >
    > > > (full text at http://aplawrence.com/Unix/perl_readonly.html ,
    > > > abbreviated version here)
    > > >
    > > > Test code:

    > >
    > > [snip code that doesn't show the problem]
    > >
    > > > foreach ("foo3","ba3") {
    > > > # doesn't like this
    > > > $dayval=$_;
    > > > caroomba($dayval);
    > > > }
    > > >
    > > >
    > > >
    > > > sub caroomba {
    > > > my $p=shift;
    > > > print "Caroomba called $p\n";
    > > > open(I,"./t");
    > > > while (<I>) {
    > > > # stuff..
    > > > }
    > > > close I;
    > > > }
    > > >
    > > >
    > > > Caroomba called foo3 Modification of a read-only value attempted at
    > > > ./t.pl line 23, <I> line 23.
    > > >
    > > > Why?
    > > >
    > > > Something to do with anonymous arrays, but I don't grok it.

    > >
    > > Which anonymous array? I don't see any.
    > >
    > > The problem is the nesting (through a sub call) of the outer
    > > for-loop and the inner while-loop. The outer "for" aliases $_
    > > to the read-only literal "foo3". This alias is still in effect
    > > inside the sub. The while-loop now tries to use the variable
    > > $_ as its implicit variable. Since $_ is aliased to a read-only
    > > value, that fails with the error you see.
    > >
    > > Anno

    >
    > OK, I see it now. If the subroutine is modified to add
    >
    > print "\$_ is $_\n";
    >
    > it shows up quickly:
    >
    > ..
    > Use of uninitialized value in concatenation (.) or string at ./t.pl
    > line 21.
    > $_ is
    > Caroomba called ba2
    > $_ is foo3
    > Caroomba called foo3
    > Modification of a read-only value attempted at ./t.pl line 24.
    >
    > I never realized that $_ would be passed down to a subroutine.. I
    > thought the sub would have its own $_.. but there it is.


    $_ is a package variable. It is the same whenever you access it.

    > So.. this isn't considered a bug or flaw in Perl? This is intended
    > behavior?


    It's expected behavior.

    Anno
     
    -berlin.de, Sep 16, 2006
    #5
  6. -berlin.de wrote:
    > Tony Lawrence <> wrote in comp.lang.perl.misc:
    > >
    > > -berlin.de wrote:
    > > > Tony Lawrence <> wrote in comp.lang.perl.misc:
    > > > > Can someone explain this to me?
    > > > >
    > > > > (full text at http://aplawrence.com/Unix/perl_readonly.html ,
    > > > > abbreviated version here)
    > > > >
    > > > > Test code:
    > > >
    > > > [snip code that doesn't show the problem]
    > > >
    > > > > foreach ("foo3","ba3") {
    > > > > # doesn't like this
    > > > > $dayval=$_;
    > > > > caroomba($dayval);
    > > > > }
    > > > >
    > > > >
    > > > >
    > > > > sub caroomba {
    > > > > my $p=shift;
    > > > > print "Caroomba called $p\n";
    > > > > open(I,"./t");
    > > > > while (<I>) {
    > > > > # stuff..
    > > > > }
    > > > > close I;
    > > > > }
    > > > >
    > > > >
    > > > > Caroomba called foo3 Modification of a read-only value attempted at
    > > > > ./t.pl line 23, <I> line 23.
    > > > >
    > > > > Why?
    > > > >
    > > > > Something to do with anonymous arrays, but I don't grok it.
    > > >
    > > > Which anonymous array? I don't see any.
    > > >
    > > > The problem is the nesting (through a sub call) of the outer
    > > > for-loop and the inner while-loop. The outer "for" aliases $_
    > > > to the read-only literal "foo3". This alias is still in effect
    > > > inside the sub. The while-loop now tries to use the variable
    > > > $_ as its implicit variable. Since $_ is aliased to a read-only
    > > > value, that fails with the error you see.
    > > >
    > > > Anno

    > >
    > > OK, I see it now. If the subroutine is modified to add
    > >
    > > print "\$_ is $_\n";
    > >
    > > it shows up quickly:
    > >
    > > ..
    > > Use of uninitialized value in concatenation (.) or string at ./t.pl
    > > line 21.
    > > $_ is
    > > Caroomba called ba2
    > > $_ is foo3
    > > Caroomba called foo3
    > > Modification of a read-only value attempted at ./t.pl line 24.
    > >
    > > I never realized that $_ would be passed down to a subroutine.. I
    > > thought the sub would have its own $_.. but there it is.

    >
    > $_ is a package variable. It is the same whenever you access it.
    >
    > > So.. this isn't considered a bug or flaw in Perl? This is intended
    > > behavior?

    >
    > It's expected behavior.
    >
    > Anno


    Ayup. I see it now, thanks. The Camel book actually tells you that
    the default variable for angle bracket input is the global $_ and not
    the local $_ (p.81 of the 3rd edition, otherwise look for the section
    on Line Input (Angle) Operator).

    I'm sure I read that at least once, but the significance escaped me -
    thanks again.
     
    Tony Lawrence, Sep 16, 2006
    #6
    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. humbleaptience
    Replies:
    0
    Views:
    5,491
    humbleaptience
    Feb 22, 2006
  2. =?Utf-8?B?am9obm55Rw==?=

    Attempted to read or write protected memory

    =?Utf-8?B?am9obm55Rw==?=, Apr 19, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    2,712
    =?Utf-8?B?am9obm55Rw==?=
    Apr 19, 2006
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,003
    Smokey Grindel
    Dec 2, 2006
  4. Jerry Preston

    Modification of a read-only value attempted

    Jerry Preston, Feb 15, 2005, in forum: Perl Misc
    Replies:
    3
    Views:
    307
    Brian McCauley
    Feb 15, 2005
  5. xyoavx
    Replies:
    7
    Views:
    115
    xyoavx
    Dec 6, 2005
Loading...

Share This Page