Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.
This function has actually been around for a while, but it’s finally documented (albeit in not much detail) in the VFP 7 help file. It tells you how many memory handles are in use.
nHandles = SYS( 1011 )
SYS(1011) can be indispensable when looking for memory leaks, either your own (because you’re not releasing every object that gets instantiated) or VFP’s (due to bugs).
SYS(1011) doesn't appear in the list of SYS() functions that IntelliSense displays when you type the opening parenthesis following "SYS". |
The absolute value returned by SYS(1011) isn’t that important; simply starting VFP 7 shows over 1,000 handles already in use. What is important is the difference in values between test runs. If you run a test several times and see nHandles increasing each time (an increase between the first two runs is simply due to memory caching and can be ignored), you’re seeing a memory leak. Whether the memory leak is your problem or VFP’s is something you’ll have to track down by finding out exactly where the memory leak is occurring.
The example shows a memory leak caused by object references that aren’t properly released. Because the two test objects reference each other, they can’t be properly released (an object isn’t released until the last reference to it is destroyed). However, the variables holding those objects (oTest1 and oTest2) go out of scope when the test program ends, so the two test objects essentially become orphaned in memory. Run the example code several times to see the effect of these orphaned objects taking up memory. Then use CLEAR ALL
and ? SYS(1011) to see the number of handles drop as these objects are finally released. Comment out the indicated line in the example code and run again several times. This time, you won’t see an increase in handles between runs; since oTest2 no longer references oTest1, releasing oTest1 (which happens when it goes out of scope at the end of the program) causes its reference to oTest2 to be destroyed, so oTest2 can be released when it goes out of scope.
? SYS(1011)
&& Displays 1298, 1302, 1308, and 1316 on consecutive runs
oTest1 = CREATEOBJECT('Test')
? SYS(1011) && Displays 1300, 1303, 1311, 1319
oTest2 = CREATEOBJECT('Test')
? SYS(1011) && Displays 1303, 1306, 1314, 1322
oTest1.oRef = oTest2
* Comment out the next line and run again to see the memory
* leak disappear.
oTest2.oRef = oTest1
? SYS(1011) && displays 1305, 1308, 1316, 1324
DEFINE CLASS Test AS CUSTOM
oRef = .NULL.
ENDDEFINE