Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Variables: NULL vs RELEASE 1

dylim

Programmer
Dec 12, 2001
159
PH
Hi Experts,

It's me once again. I have a business object that opens certain cursoradapter (CA) objects. For example, boCustomer will open the Customer CA object and the Salesman CA object.

Code:
oCustomer = NEWOBJECT( "boCustomer" )    && the Init does the creating of cursoradapters Customer and Salesman

If I, do:

Code:
oCustomer = NULL
or
RELEASE oCustomer

Both closes the associated tables, as expected, but assigning NULL to oCustomer will still "leave a remnant" :

Code:
oCustomer = NEWOBJECT( "boCustomer" )
oCustomer = NULL
? VARTYPE( oCustomer )   && returns "X" -> null

oCustomer = NEWOBJECT( "boCustomer" )
RELEASE oCustomer
? VARTYPE( oCustomer )   && returns "U" -> unknown or variable does not exist

My question is, is using RELEASE a better or safer way as it does not leave any "remnant"?

Thanks In Advance. Long Live the Fox!
 
Upfront: Whether an object releases does not depend on whether you set an object variable to NULL or release it, an object has a reference counter and is released only if that counter goes to 0,. So in a case you have 2 references on an object you could set a variable referencing it to .null., release it or both set it to .null and then release the variable, it will still not release the object!

To demonstrate this I'll use forms, not only because they are visual objects but also, because there's a gneral form count in _screen.formcount. This still holds true for all object, not only forms.

First start up a fresh VFP. Then do this in the command window (hint: You can copy this into the command window, select all the lines, right click on the selection and then "Execute Selection". Or you can execute one after the other, doesn't matter):
Code:
? _screen.Formcount
oForm1 = CreateObject("form")
? _screen.Formcount
oForm1.Left = 100
oForm1.Caption="This is Form 1"
oForm1.Show()
oForm2 = oForm1 && no new form, just adding another reference to the same form
oForm1 = .Null.
Release oForm1

1747818626676.png
This is what you should see now.
And you can test oForm1 is released, ? Vartype(oForm1) prints U - onto the form, if you don't ACTIVATE SCREEN first, but doesn't matter, the variable is gone, fully, the form still exists. It's also still healthy, there's nothing wrong with it, you can still now control it via the oForm2 variable, for example now do
Code:
oForm2.Caption = "This is also Form2"
And the Form1 caption changes.

And you can do either or both set oForm2 to .null or release it.

So the question is not giving you the essential answer, what you need to know is how objects reside in memory, they are their own memory section to which an object variable only points, they are not removed when a variable is removed from memory, they are only removed when their reference count goes to 0. So when setiting the variable to .NULL. decreases this reference count to 0 they are removed and the variable still is a variable, it just stores .NULL. now. On the other hand objects can still exist if anything else references them, while the variable is fully released.

Also, when you do both, setting null already lowers the reference count on the object, releasing it does not decrease it once more. So in the end it doesn't matter and in essence you have to learn that the object itself is separate from any reference to it, any variable, any property of other objects referring to it, anything else. Also the object reference count is part of the RAM that belongs to the object itself.

Now you might think, this isn't what I wanted to know, I don't have two references to my cursoradapter. Well, the single aspect about remnants of variables is simply that setting a variable .NULL. the variable still exists, but when the object is released, it is released, minus at worst case pending garbage collection, but that's not your concern, the runtime cares for that. For all purposes of your programming the object is released no matter if the variable still exists or not, the variable is not the object, the variable now just stores the .NULL. and needs the RAM any variable needs. The nulled variable is not a remnant of the object, it's still the variable itself that now just stored a .NULL. instead of the object reference. And so in simple cases with one varible only referring to an object, that object is already released when you set the variable .NULL., you could also set it to "bye", doesn't matter.

And to show another case: You don't have to think about objects to have RAM additional and independent of the actual variable, there are simpler things that work based on the same principle of extra allocated RAM: A string is also stored in a variable as a reference to the begin of the string RAM, and that RAM is released when the variable is released or set to .NULL. or (as you can do that in VFP, too, when you set it to anything else, like a number or date). So the string itself isn't the variable. Variables themselves only have a memory structure that can store simple data types like a number, a date or things like that with a fixed RAM size that just belongs to the actual variable RAM structure. The big difference to object variables is that cString2=cString1 will not make cString2 refer to the same RAM, the string is actually cloned into further allocated RAM to which the cString2 variable finally points to.

Variables also will be released when they are scoped local and a method or procedure or function ends and the same is true for the private scope, if it's the end of the code section that initalized them, only PUBLIC scoped variables will need to be explicitly released by you. You're free to release a less globally scoped variable though.

You could have the opposite case of what you fear about having a remnant variable, you can have a variable that still points to the RAM of the object although that is released, that's when Vartype(variable) will still tell you it's "O", an object (reference) although that reference isn't valid anymore. That's the case you have to fear, not the variable remnant you think of. It's hard to come by to that, I have no simple repro code to demonstrate that.

All in all the advice to give here is not about whether to set variable .NULL, release them or both, the advice to give is to watchout what you do with referring to objects, that you match up every creation with a release, like you have to match every opening bracket with a closing bracket. Releases can be automatic, a form in a local variable releases with the local variable. That's also the cause of beginners panicing, as they don't see why their started form immediately vanishes. You have to create a form into something that remains in scope as long as you need to form to exist, of course. It's a good idea to have a form handler or manager that you ask to start forms whenever you need them and that form manager manages the references to the forms within itself, in an array that is a property of the manager, for example or nowadays in a collection. Indeed you could base the form manager itself on the collection class. That has one big advantage regarding forms: If you release a form from within itself by calling thisform.release() or if the user just clicks the close button of the form, the collection item for the form is removed autmatically. But that's a trick you can only use for forms. It's vrey handy, though. And other objects don't have that internal this.release() method or a user interface for releasing them, so that's a problem you only face with form objects.

Well, and in simple cases like controls on forms, which also are objects, of course, they release together with the form, so they are a simple case you don't expliocitly need to care about. You can make them a non-trivial case by passing references and storing them somewhere else, though, and that can also be a reason a form doesn't release, because a control on it doesn't release. So for such references the bracket rule applies, be careful in which order you create things or pass them around and store them and thereby increase reference counts, when releasing also decrease such references first. That can get more complex then you initially think, it's still often elegant and clever to refer to other objects and store object references to forms, specific controls on forms, or a timer or any other object, too, when something else needs to refer to the same objects as the object itself or the form it is part of.
 
Last edited:

Part and Inventory Search

Sponsor

Back
Top