Nested loop crashes panx

i hope you folks will find this interesting.
it certainly has me stumped.

i have a fairly complicated (for me anyway) procedure i run once a month that does an aged inventory valuation, that is, it evaluates tranches of inventory based on when they were purchased.

last month, and many, many previous months, it ran correctly.
this month, on a new mac and new os (10.15.7), it reliably crashes panorama.

the block that causes the crash is a nested loop.
what i find very odd is that the proc runs several iterations of the loop before crashing, and it doesn’t always crash at the same place. the last two times i tried it ran 174 and 189 iterations respectively then crashed on the next one. (it would run about 700 if it worked correctly.)

this is the offending code:
i added the save near the end to see where the crash occurred. this slows the proc down enormously. it crashes with or without it.

loop
theitem = array(itms, n, ¶)
select item = theitem
theqty = val(lookup('itemlist', 'item', theitem, 'onhand', '', 0))
firstrecord
case theqty ≤ datavalue(pqty)
    ohqty = theqty    n = n + 1
case theqty > datavalue(pqty)
    ohqty = datavalue(pqty)
    theqty = theqty - datavalue(pqty)
    downrecord
    loop                                                                                 
		      if theqty ≤ datavalue(pqty)
			         ohqty = theqty    n = n + 1    stoploopif theqty ≤ datavalue(pqty)
		      else    //theqty > datavalue(pqty)
                  ohqty = datavalue(pqty)
			      theqty = theqty - datavalue(pqty)
                  downrecord
		      endif
    while forever
endcase
save

until n = arraysize(itms, ¶) + 1

i’ll happily share the entire proc if anybody’s that interested.

Are you by any chance clicking on some PanX window while the procedure is running? That can cause PanX to switch to a different database and the procedure to malfunction and possibly crash.

that has happened to me before, but that’s not the issue here. good thought though.

Sam, the loop is running O.K. at the begin; so there is no error in the code. The issue sounds like a memory issue: Something is eating up more and more memory during the loop. Do you have something like iStat Menus where you can watch Memory Usage during the loop execution?

i was very encouraged when i read your post, kurt.
thanks for replying.

i don’t have iStat menus, but i ran the proc while watching activity monitor.
i had quit just about everything i could to free up memory.
pan used c. 130-134 mb while it was running; total memory usage never exceeded 7.6 gb.
this is on a new mac pro with 32 gb of ram, so it seems there was pleanty to spare.
anyway, the proc crashed pan after 152 iterations, then after 174 iterations.
increasing available memory didn’t make any difference.

so still stuck and still stumped.

Maybe something as simple as enclosing you code within a noshow/endnoshow block might eliminate the problem. I have tried to interpret your code and then write it more in my fashion using a looparray which negates the need for incrementing the n value. I also prefer the if/elseif/else statements over the case statements. I have also enclosed the code within the noshow block as I suggested above.

Don’t know if this captures what you are trying to do or if it would keep Panorama from crashing but it might be worth a try on a copy of your database.

noshow
looparray itms,¶,theitem,n
    select item = theitem
    theqty = val(lookup('itemlist', 'item', theitem, 'onhand', '', 0))
    firstrecord
    If theqty ≤ datavalue(pqty)
        ohqty = theqty
    Elseif theqty > datavalue(pqty)
        ohqty = datavalue(pqty)
        theqty = theqty - datavalue(pqty)
        downrecord
        loop
            if theqty ≤ datavalue(pqty)
                ohqty = theqty
                stoploopif theqty ≤ datavalue(pqty)
            else
                ohqty = datavalue(pqty)
                theqty = theqty - datavalue(pqty)
                downrecord
            endif
        until info("stopped")
    Endif
endloop
showpage
endnoshow

ok, noshow/showpage by itself didn’t work.
i did get more iterations before the crash but never more than 385.
also, parenthetically, there was no visible effect from noshow: every selection, every assignment, etc was still displayed.

however, changing to looparray, a statement i didn’t know existed, did the trick! it was also way faster.

i can’t thank you enough, gary.

Wait, are you saying the looparray version didn’t crash? I did not see that coming.

However, looparray is a very cool new feature in Panorama X, I use it constantly. It makes any loop involving an array much cleaner. And it is faster, though with this complicated procedure, I am surprised that you say it is “way” faster. But that’s good news.

correct. looparray did not crash.

so apprently, jim, you thought the proc would crash with looparray? would that be because looparray increments a variable just like the loop did with loop?
i still can’t see why it crashed in the first place.
especially after looping successfully dozens of times.

The difference between looparray and the old way of doing it is that array(itms, n, ¶) needs to start at the beginning of the itms array and count off the elements until it reaches the nth element. Looparray makes its own internal copy of the array, and works its way through that. Its copy is guaranteed not to change while the loop progresses, and it remembers where the n-1st element ended, so it doesn’t have to go searching for the beginning of the nth. That makes it faster. It makes it a lot faster when it’s working with large arrays.

The actual work done during an iteration isn’t changing though. I think Jim was surprised, because he didn’t think an array( function was likely to be responsible for a crash, and that’s about the only difference between using loop, and looparray.

Gary’s version didn’t just change loop to looparray. It also changed while forever to until info("stopped"). Maybe there is something in that, but it’s hard to imagine why it crashes in different places.

I also replaced the case/endcase statements with the if/elseif/endif statements but I don’t know what part of my code Sam actually implemented.

That is exactly why I was surprised.

i did use all of gary’s code: looparray instead of loop, if elseif instead of case case, until info(‘stopped’) instead of while forever.

i initially tried my code first between noshow and endnoshow statements.
that actually got me more iterations than before, but still failed. after that i was tired of experimenting.