声明变量内存泄漏

时间:2016-08-29 21:24:23

标签: variables object vbscript memory-leaks declaration

我想知道在使用VBScript时处理内存的最正确方法是什么。应该在使用之前声明所有变量吗?该计划的开始?我理解全局vs本地,但在我的脚本中,所有变量都是本地的。我知道在99.9%的时间内用VBScript写入时内存泄漏永远不会成为问题,但我也很好奇最好的'在脚本中清除和释放内存的方法。最好的'我的意思是,清除变量/对象的时间(在你完成使用它们与脚本结束之后)等等。

一个例子:

Dim fso: Set fso = CreateObject("Scripting.FileSystemObject")
Dim arrList : Set arrList = CreateObject("System.Collections.ArrayList")
Dim objDict: Set objDic  = CreateObject( "Scripting.Dictionary")
Dim objEmail : Set objEmail = CreateObject("CDO.Message")

Dim someArray(), x, y, z, item

2 个答案:

答案 0 :(得分:3)

最佳做法是声明所有变量,但不是出于您假设的原因。 VBScript在自身清理后非常擅长清理,因此内存泄漏通常不是问题。大多数情况下,您甚至不需要释放对象(Set var = Nothing),因为它们在离开上下文时会自动销毁。

您仍然想要声明变量的原因是您希望在脚本中使用Option Explicit(强制执行变量声明),这样您就可以避免因错误输入或其他未初始化的变量而导致的问题。没有Option Explicit VBScript会自动创建缺失的变量并使用空/零值初始化它们。愚蠢的例子:

Dim foo : foo = 3
Dim bar : bar = 1
Do
  bar = bar + fo     'mistyped variable, initilized as empty/0
Loop Until bar > 10
WScript.Echo bar

运行上述操作会产生无限循环。如果添加Option Explicit,脚本将立即以运行时错误终止:

  

C:\ path \ to \ your.vbs(5,3)Microsoft VBScript运行时错误:变量未定义:'fo'

答案 1 :(得分:3)

VBScript垃圾收集器在每一行的末尾运行以清除隐式变量,并在每个过程(end subend functionend property)结束时清除显式变量。对象类似但添加了约束。它的工作方式类似于VBA的垃圾收集器。相比之下,在运行和释放内存之前,JScript会等待30,000个对象超出范围。

隐式变量是一个未命名的变量 - msgbox LCase(UCase("String")有两个隐式变量 - UCase("String")的结果,并传递给LCase(implicitVar1),返回implicitVar2传递给Msgbox。 Explict变量由DIM声明,或者仅在A=5中使用它来创建一个名为A的显式变量。

  另一方面,VBScript有一个更简单的基于堆栈的垃圾收集器。当它们进入范围时,清除器被添加到堆栈中,当它们进入范围时被移除,并且任何时候丢弃对象,它立即被释放。

https://blogs.msdn.microsoft.com/ericlippert/2003/09/17/how-do-the-script-garbage-collectors-work/

  

VBScript的垃圾收集器完全不同。它在每个语句和过程结束时运行,并且不搜索所有内存。相反,它会跟踪声明或程序中分配的所有内容;如果有任何事情超出了范围,它会立即释放它

https://blogs.msdn.microsoft.com/ericlippert/2004/12/22/t4-vbscript-and-the-terminator/

另外

https://blogs.msdn.microsoft.com/ericlippert/2004/04/28/when-are-you-required-to-set-objects-to-nothing/

https://blogs.msdn.microsoft.com/ericlippert/2004/03/01/syntax-semantics-micronesian-cults-and-novice-programmers/

CPU是基于堆栈的计算机(而VBScript是基于堆栈的虚拟机)。当CPU调用一个函数时,调用程序将参数放在堆栈和返回地址上,调整堆栈帧并进行跳转。 callee函数在堆栈上创建局部变量,并将返回值放在其上。当它返回时,堆栈指针被调回到它自动释放所有上述内容的位置。