views:

86

answers:

2

In what order are objects in a .vbs destroyed?

That is, given these globals:

Set x = New Xxx
Set y = New Yyy

I'm interested in answers to any of the following.

  1. For instances of classes implemented in the .VBS, in what order will Class_Terminate be called? Cursory poking suggests in the order (not reverse order!) of creation, but is this guaranteed?

    EDIT: I understand that Class_Terminate will be called when the last last reference to an object is released. What I meant was: in what order will x and y be released, and is it guaranteed? Assume for simplicity that x & y are the only references to their respective objects.

  2. Does the type of object matter? e.g. if I have classes implemented in the .VBS mixed in with other COM objects such as Scripting.FileSystemObject.

    EDIT: I understand that a COM library may set up its own internal circular references that the script host engine knows nothing about; I'm interested in exploring what could affect the answer to the first question.

  3. Are the answers to the above different if x and y were local to a Sub or Function rather than global?
  4. Does it depend on whether the exit is normal, by exception, or via WScript.Quit? (In the latter case, it seems that Class_Terminate is still called on any outstanding objects before exiting, however these may cause an error to be reported).
  5. When is the WScript object destroyed?
  6. Does the script host matter? (wscript.exe vs cscript.exe vs. whatever the web host engine is called)
  7. Does JScript's object destruction model differ to VBScript's?

I can find the answers to some of these questions empirically, but I'm interested in whether any of them are guaranteed / documented.

Do post even if you only know some of the answers - or further relevant issues.

+1  A: 

Eric Lippert has a couple blog posts on VBScript terminators:

Mark Cidade
Duh - I did not know they were called 'terminators' - much googling of 'destructors', 'destruction', didn't get me there :) Thanks - I'll have a read through and upvote if they answer the Q
bacar
These articles address _otherwise unterminated_ objects (e.g. due to circular references) but not the simpler case - I've revised my question to make it a little clearer.
bacar
+3  A: 

I designed and implemented this feature in VBScript.

Most of the answers are in my articles that Mark references, but just to clarify:

in what order will Class_Terminate be called?

Terminators are in general called immediately when the last reference to an object is released. However, due to circular references and other issues, it is generally a very bad idea to rely upon a deterministic order of termination.

Cursory poking suggests in the order (not reverse order!) of creation, but is this guaranteed?

As I noted in my articles, unterminated objects are terminated when the engine is shut down. As an implementation detail, the termination queue is executed in the order that the objects were created in. However, this is an undocumented implementation detail that you should not rely upon.

Does the type of object matter? e.g. if I have classes implemented in the .VBS mixed in with other COM objects such as Scripting.FileSystemObject.

It can. There could be circular references amongst those objects that are torn down at unpredictable times.

I'm thinking of objects at global scope, when the program quits - is it different for objects at e.g. function scope?

I don't understand the question. Can you clarify?

Does it depend on whether the exit is normal, by exception, or via WScript.Quit? (In the latter case, it seems that Class_Terminate is still called on any outstanding objects before exiting, however these may cause an error to be reported).

It can matter, yes. VBScript does not make any guarantee that terminators always run. The host that owns the engine can shut down its process by "failing fast" in a manner that is not guaranteed to cleanly shut down the engine, for example. (In the event of a catastrophic failure, this is sometimes desirable; if you don't know what is wrong then sometimes running termination code makes the problem worse, not better.)

Windows Script Host does attempt to shut down the engine cleanly when Quit is called.

When is the WScript object destroyed?

When the Windows Script Host process termination logic runs.

Does the script host matter? (wscript.exe vs cscript.exe vs. whatever the web host engine is called)

Yes, it can matter.

Does JScript's object destruction model differ to VBScript's?

Yes, very much so.

JScript "Classic" from the period when I worked on it (pre 2001) uses a nondeterministic mark-and-sweep garbage collector which does handle circular references amongst script objects, but does NOT handle circular references between script and browser objects. More recent versions of JScript "Classic" have a modified garbage collector that DOES handle circular references between script and browser objects (though it does not necessarily detect circularities involving JScript objects and third party ActiveX objects.)

The IE 9 version of JScript has a completely rewritten garbage collector that uses very different technology; I have chatted a bit with its designer but I do not have enough technical knowledge to discuss its characteristics in any kind of depth.

JScript .NET of course uses the CLR garbage collector.

Can I ask why you care about all this stuff?

Also, note that I haven't looked at this code in over a decade; take all of this with the appropriate level of skepticism. My memory may be faulty.

Eric Lippert
Eric, thanks for taking the time for a detailed and constructive answer. Your answer (and articles) address how _otherwise unterminated_ objects - those have not been released due to circular references ('and other issues') - are dealt with on shutdown.Otherwise, "Terminators are... called immediately when the last reference to an object is released". But in the absence of circular reference, in what order are 2 references at the same scope released, when they go out of scope? I hope that's a clearer Q and addresses the confusion around function/global.I'll update my question to clarify.
bacar
"WScript object is destroyed... when the WSH process termination logic runs" - what is 'process termination logic' in this context? Something that comes _after_ all user code, including terminators, has run?I care because 1, I am generally interested to see under the hood (and know what is guaranteed vs. implementation detail); 2. as mentioned in my comment to the Q, I suggested [using a terminator to get non-0 exit codes on unhandled errors](http://stackoverflow.com/questions/2929715/capture-any-error-in-vbscript/3720986#3720986) - I'm rapidly revising that soln in light of your answers!
bacar
@bacar: The WScript object cannot be destroyed *before* the terminators run because the terminators might call methods on the WScript object.
Eric Lippert
Exactly - I just wanted to make sure that was assured :)
bacar
Any chance of an updated answer to the updated question (and updated comments)? So I can accept your answer and be on my way :)
bacar