http://qs1969.pair.com?node_id=516543


in reply to Re^2: Out of Memory Error -- Possible Leak?
in thread Out of Memory Error -- Possible Leak?

I'm really confuzzled as to why this:

foreach my $value ( @$subarray ) {

would eat up memory.

That line expands the contents of the array into a list (Ie. On Perls' stack). If the subarray pointed by $subarray is large, it will consume a large amount of memory to do that.

You can avoid that by indexing the array, rather than aliasing it's elements. Eg.

for my $index ( 0 .. $#$subarray ) { my $value = $subarray->[ $index ]; ... }

Or, if you need to modify the elements, substitue $subarray->[ $index ] wherever you are currently using $value.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^4: Out of Memory Error -- Possible Leak?
by graff (Chancellor) on Dec 15, 2005 at 06:06 UTC
    That line expands the contents of the array into a list (Ie. On Perls' stack). If the subarray pointed by $subarray is large, it will consume a large amount of memory to do that.

    But... but... wait a minute. I thought that in this sort of loop:

    for $value ( @array ) { # or ( @$arrayref ) # do something with $value }
    the "$value" is just being used as a "magical" reference to the actual values in the array. If you do something like $value++ inside the loop, the values of the original array are incremented in place -- the increment doesn't apply to copies of the array elements.

    So, why would that sort of loop consume extra memory? Why would it make a separate list from @array (or from the actual array pointed to by @$arrayref), when $value is being used as a reference to each array element in turn? (If it really does take up extra memory, then I'm just making clear how little I understand about the underlying implementation of for loops in perl, and if someone explains it to me, I'll probably be better off at some point...)

    The dialog so far leads me to think that the AM has some other trap or "gotcha" inside that nested loop, which hasn't been shown yet, and which is probably causing some horribly unintended consequence (e.g. something like the now-infamous sprintf bug).

    (updated to add link to Format string vulnerability)

    Another update: Okay, your reference to "Perl's stack" is probably the part I hadn't understood before: in order to process (queue-up) the elements to be iterated over, the for loop has to push the whole set of elements onto a stack. But then, I would presume that in the AM's situation, with that particulat for loop being done so many times, Perl would be re-using that stack space.

    Obviously, if the array in question is really big, the stack could boil over -- OOM -- at the first attempt on the inner-most for loop. This seems consistent with the reported symptoms, and iterating over an array index instead of array values might fix it.

      nother update: Okay, your reference to "Perl's stack" is probably the part I hadn't understood before:

      Now you've got me confused :)

      I was about to post a retraction/correct/admittion of abject failure when I saw your update. So now I'm gonna try and verify one way or another before I change anything.

      Or if A man who knows should care to step in and describe the full SP?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re^4: Out of Memory Error -- Possible Leak?
by Anonymous Monk on Dec 16, 2005 at 01:19 UTC

    Okay, I'm curious: does this matter? In my case the foreach loop is going over arrays that have ~100 elements. In this case, I would have expected the maximum memory usage to be 100 x (element-size + over-head). That doesn't seem too large, but it assumes that all memory is getting smoothly cleared after the foreach loop is finished. is that a valid assumption?

      is that a valid assumption?

      Yes. If the arrays in the loop are small it would make no appreciable difference.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.