In this post: Heartbeat: Garbage collection in VFP and .NET are similar, I talked about how the VFP name table is garbage collected.
Here’s a bug that’s been in the product since forever. It involves having a name table overflow and garbage collection occurring at an unexpected time.
Run the code below. It first calls a routine to create many random names to almost fill the name table. Then it tries to execute code in a PRG that contains many PROCs.
If the NUM is large enough, the name table will overflow, causing a name table garbage collection to occur. If the gc occurs while loading the compiled PRG object code, the partially loaded names are marked as garbage and discarded from the name table, causing seemingly random behavior, such as procedure not found or execution of the wrong procedure.
What other random behavior do you get when you run this code?
The correct behavior should be:
1. if UseNames makes the vars LOCALs, then the gc can successfully free the names and make enough room in the name table, and the test procs run correctly, with VAL and Procno changing correctly. The exact expected behavior can be seen by commenting out both the LOCAL and PUBLIC lines in UseNames
2. if UseNames makes the vars PUBLIC an error message indicating there are too many names used in the name table.
Here are some reasons why this bug is rarely encountered:
To allow many variables and execution stack, make sure your config.fpw has the lines:
UseNames(1,63000) && Make name table very full
?"Done filling name table"
FOR i = 1 TO n
cvar="x"+PADL(base,3,"0")+TRANSFORM(i) && create a unique var name like "x0011"
LOCAL (cVar) && create the var as LOCAL
* PUBLIC (cVar) && create the var as public
RETURN && Local vars get released when they go out of scope
SET TEXTMERGE off
SET TEXTMERGE to
SET TEXTMERGE ON TO (cTestName+".prg") noshow
\Procno = 0
\?"val = ",val
FOR i = 1 TO nCnt
\ PROCEDURE <<cTestName>><<i>>
\ IF VAL(SUBSTR(PROGRAM(),6)) != Procno
IF i < 100
\ val=val+" "+ program()
\ do <<cTestName>><<i+1>>
\ PROCEDURE <<cTestName>><<nCnt+1>>
\ val = val+"Jelly Bean "+TRANSFORM(<<nCnt>>)
MODIFY COMMAND (cTestName) NOWAIT