PhilBird
asked on
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.
thanks
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.
thanks
ASKER
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,IUSrDa ta)
Public
Procedure SetData(Key,Value : OLEVariant);safecall;
Procedure GetData(Key:OLEVariant; var Value:OLEVariant);SafeCall ;
Protected
procedure Initialize;override;
Destructor Destroy;override;
end;
Destructor Destroy;
begin
for t:=1 to length(MyDynamicArray) do
MyDynamicArray[t]:=unassig ned
MyDynamicArray:=nil;
{ADO Command + Dataset are created and destroyed in .GetData}
ADOConnection.Close;
ADOConnection:=nil;
Inherited;
end;
I Have a global.asa that sets the session key = nothing in the session_onEnd event.
Thanks
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,IUSrDa
Public
Procedure SetData(Key,Value : OLEVariant);safecall;
Procedure GetData(Key:OLEVariant; var Value:OLEVariant);SafeCall
Protected
procedure Initialize;override;
Destructor Destroy;override;
end;
Destructor Destroy;
begin
for t:=1 to length(MyDynamicArray) do
MyDynamicArray[t]:=unassig
MyDynamicArray:=nil;
{ADO Command + Dataset are created and destroyed in .GetData}
ADOConnection.Close;
ADOConnection:=nil;
Inherited;
end;
I Have a global.asa that sets the session key = nothing in the session_onEnd event.
Thanks
Shouldn't the destructor be public?
ASKER
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 ???????????
Thanks
Further testing by monitoring AllocMemSize and TheapStatus.TotalAllocated
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 ???????????
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
PhilBird:
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
EXPERTS:
Post your closing recommendations! No comment means you don't care.
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
EXPERTS:
Post your closing recommendations! No comment means you don't care.
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.