Gluing Strings in Place
Wilson Van Alst:
Here is a short program that illustrates the effects of garbage collection, and how it can trap the unwary:
10 clear 800 20 a$ = string$(255,"a") 30 b$ = string$(255,"b") 40 c$ = string$(255,"c") 50 gosub 100 60 b$ = mid$(b$,10,10) 70 gosub 100 80 gosub 100 90 end 100 print "a$,b$,c$ content ^:"; 110 v = varptr(a$) : gosub 200 : print v; 120 v = varptr(b$) : gosub 200 : print v; 130 v = varptr(c$) : gosub 200 : print v 140 print fre("");"free string bytes" 150 return 200 v = peek(v+1) + 256*peek(v+2) : return
Running the program will show:
- Original locations for each of the 255 byte strings
- Addresses after b$ is shortened per Line 60
- Addresses after 'garbage collection.'
"But, wait," says the unwary voice. "I see the change made in Line 60, and that affected the content location for b$. But nothing changed between Lines 70 and 80. Why do we see changes in both b$ and c$ content addresses?"
The key is in Line 140, where the program uses fre(""). This, from what I can determine, 'forces' garbage collection -- at least within the space CLEARed for string variables. So the locations reported in Lines 120 and 130 actually changed immediatly when Line 140 ran.
If you want to test this, add Line 105 to the subroutine:
105 s = fre("")
... and now you will 'force' garbage collection before computing the string content addresses.
Alternatively, don't use Line 105 and also get rid of Line 140. Without the fre("") command, no garbage collection is performed, and the contents of b$ and c$ stay where they were.
Lessons for those who might want to put machine language in a string to be called at its VARPTR address pointers:
- You can force garbage collection immediately before computing the CALL address and then, as far as I can tell, be confident of hitting the right spot (though recognizing that this absolute address may have changed since the first time you created your string.)
- You can create a string for m/l instructions at the very start of your program. As long as you do nothing to change the length of this string, its content location should not be affected by garbage collection. [Note, in the above program, that the location of A$ did not change.]
- With the preceding in mind, it would appear possible to define not just one, but several, strings-full of m/l instructions at the start of a program. The strings' contents would be written contiguously at the top range of string storage space, apparently immune to garbage collection, and could thus hold an m/l program of more than 255 bytes. [Note that careful construction of these strings would be needed -- since the first 255 bytes of your program would go into the last string written ... while the program's final (length mod 255) bytes would go into the first string.]
Some un-answered questions that may trash all of the conclusions above:
- What else, besides fre(""), forces garbage collection?
- What else, besides garbage collection, messes with string content pointers?
- What else have I neglected to consider?