Another possible cause.
Running interrupts? If the proper context isn't saved then it will run almost all the time without a problem until the particular context that isn't saved happens to be in use in user code when an interrupt happens. The longer the code runs, the more chances you'll finally hit the timing needed to make this happen.
For example, PCLAT isn't saved but a computed function call is executed in the interrupt routine which uses the PCLAT AND the interrupt happened to catch the user code doing the same thing and it was partially through loading the registers (for example PCLATH loaded but not PCLAT)... upon returning the user code finishes the computed call and vectors off in some random program memory because the data in PCLAT is left over from the interrupt routine and not what the user code had loaded.
Similar issues can exist with any of the other compiler managed resources.
The easiest way to test this is to load up the save= list will ALL compiler managed resources and see if the code can run longer idling without RLOD.
Code:
save=PROD,TBLPTR,TABLAT, PCLATH,PCLATU,section(".tmpdata"),section("MATH_DATA")
I think that covers them all.