Thursday, April 17, 2008

COM Objects are not destroyed when using Server.CreateObject in Classic ASP (Jscript)

Recently it was discovered that, on a particular ASP page in our application, COM objects that were being created using Server.CreateObject were not being properly destroyed. Actually, I should rephrase that, they weren't being destroyed at all until the component services package was shut down. If I kept task manager open, and watched the mem usage of dllhost.exe, I could see the memory being used by the processed increased each time I hit the page in question, and never decreased. Also, if I went to Administrative Tools -> Component Services and looked at the Objects, Activated, and In Call columns for the COM objects in my package, I could see those numbers ever increasing without decreasing.

The code is written in JScript and looked something like this:
var o = Server.CreateObject("dllname");

/* do stuff... */

o = null; //<--- I thought that this line should cause this object to be destroyed, I was //wrong
After much searching I came across this article: PRB: COM Objects Created in JScript Not Released Immediately. The article basically says that because JScript uses deferred garbage (for performance reasons), it can sometimes delay object destruction (in my case, permanently delay it). The article offers two solutions, the first suggest that a destructor be written for the dll, and the second suggests that the undocumented CollectGarbage() function be used. I chose the latter, simply because adding to the dll would be a bigger inconvenience (aka laziness).

A third suggestion that I would suggest, just based on conjecture from information provided in the article, is to rewrite the code block causing the problem in vbscript, as it is not effected by this problem (no garbage collection).

As for my problem, I'm not entirely sure why the problem occurs on only one page and not the others. My only guess is that on the page that is having a problem all of the COM objects are instantiated (about 14), whereas on most others only one or two objects are created.

The following is my code, after I fixed it:
var o = Server.CreateObject("dllname");

/* do stuff... */

o = null;

CollectGarbage(); // <-- This one little line fixed my problem

No comments: