Is there a need to set Objects to Nothing inside VBA Functions

你离开我真会死。 提交于 2019-11-26 01:59:41

问题


I always read that it is recommended to set objects to nothing, once I am done with them. But I normally use them only in functions inside forms.

Isn\'t the reference lost and memory released when the function scope is left, regardless of setting objects to Nothing?

i.e. is it really necessary to do:

Set db = Nothing
Set record_set = Nothing

回答1:


VB uses a so-called "reference counting" garbage collector.

Basically, the moment a variable goes out of scope, the reference counter on the referenced object is decremented. When you assign the object reference to another variable, the reference counter is incremented.

When the counter reaches zero, the object is ready for garbage collection. The object resources will be released as soon as this happens. A function local variable will most likely reference an object whose reference count never goes higher than 1, so object resources will be released when the function ends.

Setting a variable to Nothing is the way to decrease the the reference counter explicitly.

For example, you read in a file, and set the file object variable to Nothing right after the ReadAll() call. The file handle will be released immediately, you can take your time process its contents.

If you don't set to Nothing, the file handle might be open longer than absolutely necessary.

If you are not in a "must unblock valuable resource" kind of situation, simply letting the variables go out of scope is okay.




回答2:


Garbage collection is rarely perfect. Even in .NET there are times where you are strongly encouraged to prompt the system to do garbage collection early.

For this reason, I explicitly both close and set to Nothing recordsets when I'm done with them.




回答3:


The very last line of the help topic for "Recordset.Close" in the Microsoft DAO help and the Access Developer Reference is this:

"An alternative to the Close method is to set the value of an object variable to Nothing (Set dbsTemp = Nothing)."

http://msdn.microsoft.com/en-us/library/bb243098.aspx

With that in mind, this article from the Microsoft Knowledge Base entitled "How to prevent database bloat after you use Data Access Objects (DAO)", tells you that you should explicitly close if you don't want your databases to bloat. You'll notice that the article is a little vague about the details; the "Cause" section is unclear, almost to the point of being gibberish.

http://support.microsoft.com/kb/289562

SYMPTOMS: A Microsoft Access database has begun to bloat (or grow rapidly in size) after you implement Data Access Objects (DAO) to open a recordset.

CAUSE: If you do not release a recordset's memory each time that you loop through the recordset code, DAO may recompile, using more memory and increasing the size of the database.

MORE INFORMATION: When you create a Recordset (or a QueryDef) object in code, explicitly close the object when you are finished. Microsoft Access automatically closes Recordset and QueryDef objects under most circumstances. However, if you explicitly close the object in your code, you can avoid occasional instances when the object remains open.

Finally, let me add that I have been working with Access databases for 15 years, and I almost always let my locally declared recordset variables go out of scope without explicitly using the Close method. I have not done any testing on it, but it does not seem to matter.




回答4:


References are supposed to be cleaned up when the variable goes out of scope. Presumably this has improved with later versions of the software, but it was at one time not reliable. I believe that it remains a good practice to explicitly set variables to "Nothing."




回答5:


When you are using ASP classic (server-side scripting), it is import to set all objects to nothing when you are through with them, because they do not go out of scope until the [virtual] server is shut down.

For this reason, all MS VB scripting examples always showed objects being closed and set to nothing. So that the script excerpts could be used in environments like ASP classic where the objects did not go out of scope.

There are, rarely, other situations where you wish to code long-running processes where the objects do not go out of scope, and you find yourself running out of physical memory if you do not explicitly release objects.

If you find yourself coding ASP classic, or running processes in global scope for some other reason, then yes, you should explicitly release objects.




回答6:


I usually always put this at the end of my procedures, or call a "CloseRecordSet" sub with it in if I'm using module level ones:

Private Sub Rawr()
On Error GoTo ErrorHandler

    'Procedural Code Here.

    ExitPoint:
        'Closes and Destroys RecordSet Objects.
        If Not Recset Is Nothing Then
            If Recset.State = 1 Then
                Recset.Close
                Conn.Close
            End If
            Set Recset = Nothing
            Set Conn = Nothing
        End If
        Exit Sub

    ErrorHandler:
        'Error Handling / Reporting Here.
        Resume ExitPoint
End Sub

That way however the procedure ends, (be it normally or due to an error) the objects are cleaned up and resources are free.

Doing it that way is quite safe in that it you can just slap it in and it will only do what is necessary in regards to closing, or destroying the recordset / connection object, incase it has already been closed (due to a runtime error or just closing it early as ya should, this just makes sure).

Its really not much hassle and its always best to clean up your objects when you're finished with them to free up resources immediately regardless of what happens in the program.




回答7:


Try this

If Not IsEmpty(vMyVariant) Then
    Erase vMyVariant
    vMyVariant = Empty
End If


来源:https://stackoverflow.com/questions/517006/is-there-a-need-to-set-objects-to-nothing-inside-vba-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!