Playdate->system->listfiles crashing on device, not in simulator

Here are some of the things I learned this week trying to figure out my crash. I tried to map it to using listfiles. You may know all of this, but maybe there is something here that helps.

  • Since you're only crashing on the device could be related to a hidden file like .DS_Store . Shouldn't actually cause a crash, but I'm trying to think why you crash on device but not simulator.
  • I saw here that the stack might be ≈61 KB, trying to use more than that might crash. Not certain on that number though.
  • Frequent malloc/free cycles can cause you to run out of heap. Fragmentation.
  • Mixing standard malloc/free and pd->system->realloc/free creates 2 separate heaps. Freeing with the wrong allocator corrupts.
  • Avoid file system API calls including listfiles from inside the callback since it’s running while the system is iterating the directly. Could be that the simulator runs faster and finishes iterating before the device does.
  • Don't store the pointer for use after the callback returns. If you need it later, copy const char* filename to your own buffer. You can do this in the callback. If you are doing this, it could be where the corruption is happening (see next bullets).
  • Trimming strings might accidentally trim off the \0 resulting in a non-terminated one (Relates to storing the filenames)
  • Watch out for off-by-one when appending filenames … the / on directories can throw off the count
  • Avoid Non-ASCII or very long names. I didn't find anything that said this was a problem, but could be a difference between the computer and the device maybe? Sound's like a best practice.

Things you can do to debug…

  • Strip back your callback then re-introduce one piece at a time. Probably hard to do as this will probably break your game. Maybe you could pull out each piece into a new function? Goal is to get to a callback that doesn't allocate or parse anything and see if it still breaks or if the break moves somewhere else.
  • If you are allocating in the callback, wrap with guards to detect overruns or double frees. (This is what I was starting to do although I wasn't using listfiles.) Maybe you could detect overruns or double frees with the simulator Malloc Log, but I don't know how, seems like too much going on there to find the needle in the haystack.
  • Use playdate->file->stat to confirm it’s a directory before calling listfiles.

Edit: I meant to reply to @bribri ‘s post just above, not this one.