Tho*_*ith 4 vbscript garbage-collection scope asp-classic
我有以下代码:
function p (str)
Response.Write VBLF & str
end function
function nop: end function
class Test1
private sub class_initialize
p "Test1 Start"
end sub
private sub class_terminate
p "Test1 End"
end sub
end class
class Test2
private sub class_initialize
p " Test2 Start"
end sub
private sub class_terminate
p " Test2 End"
end sub
end class
Run Code Online (Sandbox Code Playgroud)
当我跑:
with new Test1
with new Test2
end with
end with
Run Code Online (Sandbox Code Playgroud)
我期待输出:
Test1 Start
Test2 Start
Test2 End
Test1 End
Run Code Online (Sandbox Code Playgroud)
但我得到:
Test1 Start
Test2 Start
Test1 End
Test2 End
Run Code Online (Sandbox Code Playgroud)
但是,如果我运行以下任一项,我会得到我的预期:
with new Test1
with new Test2
nop
end with
end with
with new Test1
with new Test2
end with
nop
end with
Run Code Online (Sandbox Code Playgroud)
但不是以下内容:
with new Test1
nop
with new Test2
end with
end with
Run Code Online (Sandbox Code Playgroud)
VBScript对GC的对象有相当强的保证,我在我的应用程序中使用(滥用?)这种保证用于各种目的.没有nop,为什么它收集Test1和Test2"错误"的顺序?
Eri*_*ert 10
多么迷人的bug.
我没有方便的VBScript引擎的调试版本.(自从我上次查看它以来的两年里,我保留它的十年硬盘显然已经坏了.)但是,我可以很容易地猜到这里发生了什么.我怀疑是我没有将对应于"end with"的指令标记为语句结束且收集器必须运行的点.
让我们考虑一下这个假设.
在您的第一个示例中,GC何时运行?程序结束时.此时,终结符按创建对象的顺序运行.(这是您不应该依赖的实现细节.)
在你的第二个和第三个例子中,对nop的调用结束会触发一个GC,这就发生在接下来的结尾处.(我不太清楚为什么第二个例子在对象有资格收集时触发GC;我不记得codegen的确切语义,用于从with block范围中弹出对象引用.)
在您的第四个示例中,GC在内部使用之前触发,并且不执行任何操作.
由于我写了终止逻辑和相当数量的"带"处理代码,我无疑造成了这个错误,所以很多道歉.很明显,在过去的十一年或十二年里,我们与它一起生活并没有出现重大问题,而且由于它只影响没有内容的"有"块,我不认为它会被修复.
无论如何,你不应该依赖终止令.这是一个糟糕的编程习惯.
有关VBScript终止逻辑的迷人主题的更多信息,请参阅: