My memory failed me for a bit there. Yes, all versions of QuickBasic and QBasic use string descriptors for variable-length strings, and fixed-length strings have no descriptors.
The "undocumented behaviour" is the contents of these descriptors. In QBasic, QB 4.5, and QB 7.1 compiled with near strings, these are all the same.
In QB 7.1, compiled with far strings, OR interpreted, the format of the string descriptors are different. The gory details are in Winer Chapter 2.
For the record, I tried compiling your program in 7.1 with near strings. Didn't crash.
My preferred solution is to steer clear of strings. Generally by using arrays. You *can* portably use fixed-length strings if you wrap them up in a TYPE (as suggested by Winer in Chapter 12) or be careful to ONLY pass their address, never the actual string, as an argument to a procedure.
>It's my understanding that both will also automatically reorganize variable-length string character data as memory fragmentation increases over time, though I do not know specific details.
Only if you do anything that requires the creation of a string (that is, string assignment, concatenation, or using functions that return strings like CHR$() or MID$() or MD5IReturnAString$; ASC() and LEN() are fine). If none of these things happens in between getting the address of string data and using the address, then there's nothing to worry about.