So one of my favourite Palm games is called Pocket Rogue. Finding the binary on the internets isn't too hard but the source code is another issue altogether. The source is something I've wanted to get access to ever since I got my Treo 650 because there are things the game could do better on this system (eg. high-res bitmaps, better support for the keyboard). I eventually stumbled onto the code one day
a while back and re-did the work to make it build under PRC-Tools (I originally did this years ago when I had a Visor Edge).
So anyway, the app randomly crashed on me and I couldn't figure out why.
Thanks to my recent discovery of
How to debug apps under POSE I now know the reason. It's because of this:
static char *pos = "\010\007\001\003\004\005\002\006\0";
...
pos[x] = pos[y];
That is, the 'pos' buffer is meant to be initialised to a particular value, is preserved across invocations of this function and may be modified (this 'may be' is why the crashes were random).
The Pocket Rogue source code is a CodeWarrior project so clearly this construct works with the CodeWarrior compiler but it fails in GCC because *foo ends up referring to data in the storage heap and modifying that without using DmSet causes a crash.
WTF?
Actually, it does make sense. You see "some string" is a literal string and modifying a literal string has undefined behaviour (according to the standards). A literal string should be considered a 'const char*' (or for C++ people, char const *). That is, you get a pointer to data that is constant. While some implementations/compilers happen to put string literals into memory that can be overwritten, this is not guaranteed. In the case of GCC for Palm OS, the pointer you get points to the string inside the binary, which of course resides in the data heap (or for NVFS devices, DBCache).
The correct way to initialise this is with code like this:
static char pos[10] = "\010\007\001\003\004\005\002\006\0";
What's the difference?
The bad version said "assign to this pointer the value of this string literal" which gives us an address to read-only memory. The updated version says "copy this string literal into this 10 byte character array" which means a memcpy is done behind the scenes.
I would guess that this is what CodeWarrior was doing implicitly.