在 VB6/VBA 中是否真的需要对象清除/数组释放(优点/缺点?)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1525772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is object clearing/array deallocation really necessary in VB6/VBA (Pros/Cons?)
提问by Oorang
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?
我从使用静态代码分析(尤其是 Aivosto 的项目分析器)中学到的很多关于 VB 的知识。它检查的一件事是您是否清除了所有对象和数组。我以前只是盲目地这样做,因为 PA 是这么说的。但是现在我对 VB 释放资源的方式有了更多的了解,在我看来,这些事情应该是自动发生的。这是 VB6 之前的遗留功能,还是您应该明确将对象设置为空并在数组上使用 Erase 的原因?
采纳答案by Mike Hofer
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.
据我了解,这个问题与 VB6(及其前身)的根源在于 COM 及其引用计数垃圾收集系统的事实有关。
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.
例如,想象一下,您声明了对来自 3rd 方库的对象的引用。该对象有一个 COM 引用计数,用于使其保持活动状态并确定何时应销毁它。当您将其设置为 Nothing 时,它不会被销毁,但是当对象的引用计数达到零时。
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.)
现在,并非所有 COM 组件都是用 Visual Basic 编写的。有些是用 C 或 C++ 编写的。并非所有语言都存在结构化异常处理。因此,如果发生错误,则无法保证对象的引用计数会适当减少,并且已知 COM 对象会比预期的停留时间更长。这对 Visual Basic 本身来说不是问题。这是一个COM问题。(您可能会注意到,这就是 .NET 不使用引用计数的原因。)
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.
这就是为什么 Visual Basic 开发人员对在退出例程之前释放对象引用非常着迷的原因。您根本不知道您正在分配的组件在后台创建了什么。但是当你释放对它的引用时,你至少释放了对它的引用计数。它几乎成了一种宗教咒语。声明、使用、释放。这是 COM 的做事方式。
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.
当然,Visual Basic 在取消引用我在堆栈上声明的变量时可能会更好或更快。但是该死的,我希望这些物体被释放是显而易见的。当您试图追踪内存泄漏时,一点保证大有帮助。
回答by onedaywhen
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:
Matt Curland,Advanced Visual Basic 6 的作者,他比我们大多数人更了解 Visual Basic,认为这是白费力气。考虑一下有关 DAO 的引用 (p110),它是主要针对 Access 数据库引擎的 COM 数据访问库:
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.
另一个糟糕的拆卸代码示例。DAO 具有必须以正确顺序调用的 Close 方法,并且对象也必须以正确顺序释放(例如,Recordset 在 Database 之前)。这种单一的不良对象模型行为导致了一种误解,即除非您在函数末尾将所有局部变量显式设置为空,否则 VB 会泄漏内存。在设计良好的对象模型中,这是一个完全错误的概念。VB 可以比从代码中更快地清除 End Sub 行中的变量,并且即使您显式释放引用,它也会检查变量。你所做的任何努力都是重复的。
回答by MarkJ
Have you read this Aivosto web page(from the creators of Project Analyzer)?
您是否阅读过这个Aivosto 网页(来自项目分析器的创建者)?
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.
换句话说,您无需担心清除普通的、非静态的、局部变量。
回答by JonH
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.
我总是为了良好的实践而这样做,你永远不知道如果你陷入一个异常并且你的对象没有被释放,它会做什么。您应该在 finally 语句中释放它们并确保它们没有使用任何内存,否则您可能会遇到内存泄漏。
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.
我在一个简单的超时跟踪器系统中遇到了一个问题,其中服务器不断随机崩溃,花了数周时间才确定这是一个应该自行自毁的对象的内存泄漏。我的代码被抛出异常并且在其自身导致服务器(实际网站而不是整个服务器)关闭后从未清理过。
回答by HardCode
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.
是的,将所有对象设置为 Nothing 并尽可能多地清理。VB6 因在不清理东西时发生内存泄漏而臭名昭著。垃圾收集在 VB6/VBA 中低于标准。