views:

903

answers:

5

Hello, A lot of what I have learned about VB I learned from using Static Code Analysis (Particularly Aivosto's Project Analyzer). And one one of things it checks for is whether or not you cleared all objects and arrays. I used to just do this blindly because PA said so. But now that I know a little bit more about the way VB releases resources, it seems to me that these things should be happening automatically. Is this a legacy feature from pre VB6, or is there a reason why you should explicitly set objects back to nothing and use Erase on arrays?

A: 

I always do it for good practice, you never know what an exception might do if you fall in one and your objects are not deallocated. You should relase them in finally statements and ensure they are not using any memory otherwise you may run into a memory leak.

I had an issue inside of a simple time off tracker system where the server kept on crashing randomly, it took weeks to determine it was a memory leak of an object that was supposed to self destruct on its own. My code was being thrown into an exception and never cleaned up after itself causing the server (the actual web site not the entire server) to go down.

JonH
Interesting, may ask what type of object it was? What was it's scope? Was it a trappable exception being thrown, or did the app just crash out? When a standard exception is thrown the procedure is exited. Even if by exception, all local references are still automatically destroyed. So if there were no references to the object outside the procedure, what was causing the object to stay "alive"?
Oorang
There are no Try/Catch/Finally blocks or Exceptions in VB6/VBA.
HardCode
There are no Try/Catch/Finally blocks, but there are trappable exceptions. Have a look at Err.Raise.
Oorang
Right I know there isnt in VB6, my point is there may be something similiar. I havent done vb6 in quite some time sorry :).
JonH
A: 

Yes, set all objects to Nothing and clean up as much as you can. VB6 is notorious for having memory leaks when not cleaning up your stuff. Garbage collection was sub-par in VB6/VBA.

HardCode
Hi HardCode, I have often heard this sentiment expressed. What I am trying for though is a concrete/reproducible example?
Oorang
There's nothing wrong with VB6's garbage collection mechanism. It's other components that don't properly release references or which require very specific teardown semantics that break it. It's not VB6's fault that there are poorly-written components that don't follow the rules.
Mike Spross
Sometimes you need to explicitly tear down things such as circular object references as well. In general scope-exit will release local refences and deallocate arrays but in a long-lived scope such as module-global data you might be well advised to tactically clean up early on occasion just to free memory resources.The point is there just isn't a general rule. You need to be aware of what you're doing and when there is value in early deallocation.
Bob Riemersma
@Bob: Good point. I think we agree actually: the point is indeed that there simply isn't a hard-and-fast rule for releasing objects. The "everything-must-be-released-always-no-matter-what" mentality seems to have originated out of want for a rule that can be consistently applied in every situation, and I can't say it's "wrong" to work under that assumption, but I think it's better to understand how GC works in VB6, so you can make an informed decision. What bothers me is people get this idea that VB6's memory management is horribly broken, but that's just an incorrect conclusion.
Mike Spross
Thanks Bob and Mike, good discussion. I tend to agree with Mike that you shouldn't do anything without a good reason. And I think Bob defiantly presents a scenario where you might have a good reason:) +1 2 you both:)
Oorang
+8  A: 

Matt Curland, author of Advanced Visual Basic 6, who knows more about Visual Basic than most of us ever will, thinks it is wasted effort. Consider this quote (p110) about DAO, the COM data access library that primarily targets the Access Database Engine:

another example of poor teardown code. DAO has Close methods that must be called in the correct order, and the objects must be released in the correct order as well (Recordset before Database, for example). This single poor object model behavior has led to the misconception that VB leaks memory unless you explicitly set all the local variables to nothing at the end of a function. This is a completely false notion in a well-designed object model. VB can clear the variables faster at the End Sub line than you can from code, and it checks the variables even if you explicitly release your references. Any effort you make is duplicated.

onedaywhen
If Matt Curland told you to jump off a bridge, would you?
JonH
Hi ODW, This parallels my line of thinking. DAO is the only object that I knew for sure had to be released correctly (outside of Win32). Are you aware of any other "special cases"?
Oorang
@JonH: If Matt Curland proved himself to be a world-leading expert at bungee jumping and I was inclined to try it myself then probably yes.
onedaywhen
+1 If could have accepted two I would have accepted this as well. Good discussion of the topic. I think maybe my take away from this is that if you know the objects don't leak, don't waste time. If you aren't sure, then find out. If you can't find out, then clear to be safe.
Oorang
+4  A: 

The problem, as I understand it, has to do with the fact that VB6 (and its predecessors) has its roots in COM, and its reference-counting garbage collection system.

Imagine, for instance, that you declare a refernece to an object from a 3rd party library. That object has a COM reference count that is used both to keep it alive and to determine when it should be destroyed. It isn't destroyed when you set it to Nothing, but when the object's reference count reaches zero.

Now, not all COM components were written in Visual Basic. Some were written in C or C++. Structured exception handling didn't exist across all languages. So if an error occurred, the reference count on the object was not guaranteed to be properly reduced, and COM objects were known to hang around longer than they were intended to. This wasn't a problem with Visual Basic, per se. It was a COM problem. (And that, you might note, is why .NET doesn't use reference counting.)

That's why Visual Basic developers became obsessive about releasing object references prior to exiting routines. You simply don't know what a component you're allocating is creating under the hood. But when you release your reference to it, you're at least releasing your reference count to it. It became almost a religious mantra. Declare, use, release. It was the COM way of doing things.

Sure, Visual Basic might be better or faster at dereferencing variables I declared on the stack. But dammit, I want it to be OBVIOUS that those objects were released. A little assurance goes a long way when you're trying to track down a memory leak.

Mike Hofer
Accepted. I think this best speaks to what I was digging for which was what obsessive clearing might be preventing. I hate to do things just because "that's the way we always have". I also think maybe in scenarios where you know the objects really well it's probably OK to just let them drop out of scope.
Oorang
+1  A: 

Have you read this Aivosto web page (from the creators of Project Analyzer)?

If you are using static variables, it's important to reclaim the memory they occupied when you don't need the variables any more. With dynamic variables memory isn't so much of a problem, because they are destroyed when the procedure ends.

In other words, you don't need to worry about clearing ordinary, non-static, local variables.

MarkJ
+1 For noticing that:) Although it's a pretty rare day when I am using statics. I usually just use private module level variables if I need something remembered.
Oorang