Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 374
  • Last Modified:

TASPMTSObject not calling destructor

I'm building a TASPMTSObject to use from an ASP page.

In my testing I'm seeing DLLHost's memory consumption grow considerably (~2 MB per instance @ 1 instance per user) an not drop much (~200 K) when the session ends.
I've discovered that my Destructor which overrides .Destroy is not being called.

Is this normal? should I be overriding .ObjRelease instead?
I'm concerned that the object instances are not being destroyed let alone my private variables.

I'm using Delphi 6.0 w/ sp2 on W2k and IIS 5.0
I'm testing my object in a seperate instance of dllhost to isolate from iis thru component services.

1 Solution
2 MB per instance is pretty large.

What are you storing there?

Are you storing anything in the session?

After overriding .ObjRelease  is a better idea than overriding the destructor destroy should be called althrogh this. But withing the MTS that does not have to happen immedeately.

Is your destructor never called?

Probably you can give as a little bit of sample code that we can get a better picture.
PhilBirdAuthor Commented:
It stores 15 to 20 variants which are used to store strings and integers which are the state data for the users session in a dynamic array of variant not a variant array. The object itself is stored in the session.

it declares a private TADOConnection, TADOCommand and a TADODataSet to store the variants to the Database and retrieve previous values from a previous session for the same user. The plan is that it only goes to the DB when a value is requested that it does not already have.

The destructor never gets called. not even when MTS Ends the DLLHost process.

Currently I'm overriding .ObjRelease and calling destroy when .refCount < 1

the ASP page never calls release or destroy I just set the variant = nothing

the codes looks like:

TUsrData = Class(TASPMTSObject,IUSrData)
           Procedure SetData(Key,Value : OLEVariant);safecall;
           Procedure GetData(Key:OLEVariant; var Value:OLEVariant);SafeCall;
           procedure Initialize;override;
           Destructor Destroy;override;

Destructor Destroy;

     for t:=1 to length(MyDynamicArray) do
     {ADO Command + Dataset are created and destroyed in .GetData}

I Have a global.asa that sets the session key = nothing in the session_onEnd event.

Shouldn't the destructor be public?
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

PhilBirdAuthor Commented:
Perhaps, But Destroy is called by TComobject.ObjRelease therefore scope isn't really an issue. I've also confirmed that TComObject.Destroy is not being called as well.

Further testing by monitoring AllocMemSize and TheapStatus.TotalAllocated indicate all memory being allocated is being free'd when myObject.RefCount <= 0 as  it should. So I no longer think the destructor is the issue though it would have been nice if it worked. I'm now deallocating resources in my .ObjRelease function.

I belive the reason DllHost and my test program suck up ever increasing amounts of memory is due to the windows memory allocation scheme. I think it's designed to allocate new objects always at the end of previous objects even if they are free'd until it hits a threashold and does a compact of the heap. since the process address space is 2-4 GB that's why AllocMemSize reports that the amount of memory being allocated is not growing but Task manager shows the memory footprint growing.

So, This leaves me with a new twist. I Even though this may be correct I don't want my program to grow to 50+ MB when it only needs 2MB due to fast memory allocation. The Win32 api documents a "HeapCompact" function that may resolve my problem. However to use it I need the handle to the heap where my objects are being allocated. To get a handle to the heap I need to use the GetProcessHeaps function, but I can't get it to accept a pointer to a buffer in D6. The compiler wants a Cardinal but I can't seem to find a way to use a cardinal to pass a pointer to a buffer.

How do I get a buffer of Heap handles from GetProcessHeaps in D6 ???????????

To access the buffer try the following:

  PHandle = ^Handle;
  myPhandle : PHandle;
  NumberOfHeaps, NumberOfValidHeaps: integer;
  ProcessHeaps : Cardinal;
  NumberOfValidHeaps := GetProcessHeaps(NumberOfHeaps,ProcessHeaps );
  myPhandle  := PHandle(ProcessHeaps);

the MTS is managing his memory himself, so it sounds no good idea to try to manipupate this!

Have you checked out the pooling options in the MTS? probably they'll help.
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
Post your closing recommendations!  No comment means you don't care.

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now