http://www.perlmonks.org?node_id=1001362

schetchik has asked for the wisdom of the Perl Monks concerning the following question:

Hello!

Could you explain, why does wrong dereference make my Perl out of memory

$ perl -e 'my $a = [{ test => { val => 1 } }, { test => { val => 2} }] +;print $a->{test}->{val}, "\n"' Out of memory!
I use perl 5.8.8

Thank you

Replies are listed 'Best First'.
Re: Wrong dereference => Out of memory
by Anonymous Monk on Oct 29, 2012 at 15:10 UTC

    First of all, this is about pseudo-hashes. This (now long gone) feature lets you access an array reference as if it was a hash reference.

    So what does $aref->{key} actually do? Well, this: $aref->[$aref->[0]{key}]. That is, it fetches the first element of the array (which must be a hashref) and uses it to map the key to an array index, which is then finally looked up in @$aref.

    The other piece of the puzzle is autovivification (also explained in perldoc perlref). This is what automatically creates references for you when you try to dereference something that doesn't exist. Example:

    my $foo; $foo->[1] = 42; # automatically sets $foo = [] before the # assignment so you end up with $foo = [undef, 42] instead of # dying with "Can't use undef as an ARRAY reference"

    OK, now let's look at your code again. $a->{test} looks up "test" in { test => { val => 1 }} (the first element of @$a) and returns { val => 1 }. It then uses this reference as an array index, which converts it to a (very large) integer (the internal memory address of the hash).

    $a->[0xDEADBEEF] obviously doesn't exist; the array only has two elements. But since you're dereferencing it (the ->{val} part), perl tries to autovivify a hashref for you. Unfortunately this involves resizing the array to have 0xDEADBEEF + 1 elements (the intervening elements are set to undef). At this point perl is running out of memory, as expected.

      Meh. By the time I've figured it out, somebody else has already posted a perfect explanation!

      I'd ++ you if you weren't an anonymous monk.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Thank you very much.

      I agree, it's a great explanation.

      Sorry, i can't put more then one plus for you message :)

Re: Wrong dereference => Out of memory
by Athanasius (Archbishop) on Oct 29, 2012 at 14:44 UTC

    Well, I can’t answer your question, sorry :-(.

    But I can confirm that, whatever was going on in version 5.8.8 (which I don’t have), was fixed by version 5.10.1:

    0:39 >perl -e " my $a = [ { test => { val => 1 } }, { test => { val = +> 2 } } ]; print $a->{test}->{val}, qq[\n] " Not a HASH reference at -e line 1. 0:39 >

    Hope that is of some help,

    Athanasius <°(((><contra mundum

      It looks like pseudo-hashes to me?

      My best guess is that $a->{test} out-of-memories because there are two test fields, which is not supposed to happen in pseudo-hashes because... uh... everybody's super extra careful all the time, right?

      Anyway, they were promptly deprecated and then removed by 5.10.0, so that would be why you get a normal error message and the OP doesn't.

      EDIT: an Anonymous Monk explains the same thing with many more details a couple posts down.

Re: Wrong dereference => Out of memory
by fullermd (Priest) on Oct 29, 2012 at 14:53 UTC

    I would guess it doesn't really run out of memory, so much as trigger some error whose generic error message is "out of memory" (ENOMEM or the like), so you get the generic message which isn't quite appropriate to your case.

      I'm sorry, but it is not :)

      I see great increase of memory usage, when this script is working.

        Ah, in that case ignore me :)

        The pseudo-hash discussion below is probably right then. I'd forgotten (not accidentally) they ever existed...

      It totally does run out of memory! It causes Perl to spin into oblivion!

      I know what causes it. I'll explain below...

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Wrong dereference => Out of memory
by kennethk (Abbot) on Oct 29, 2012 at 15:16 UTC
    What's your OS? With ActiveState v5.8.9 (MS) I just get a silent fail from dereferencing undefined values.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.