Board index » delphi » THHTPRIO component is freed after calling a remote method if it has no owner

THHTPRIO component is freed after calling a remote method if it has no owner


2007-03-16 10:16:21 AM
delphi277
Hi everyone.
Last week for the very first time I needed to create a instance of THTTPRIO
in run-time. As its lifetime was short I created it without an owner. So
I got surprised when my application raised an access violation after calling
THTTPRIO's Free method. I found out the instance was freed before its destructor
to be executed, and that made no sense to me since THTTPRIO class inherits
from TComponent and its Owner was set to nil.
So I started digging in SOAP source code and I figured out who is to blame:
function TRIO._ReleaseFromIntf: Integer; stdcall;
begin
{ Adjust the self pointer to point to the actual object, not }
{ our little generated vtable slot. }
Self := AddPtr(Self, -Integer(LongWord(@Self.IntfTable) - LongWord(Self)));
Result := InterlockedDecrement(FRefCount);
if (Result = 0) and not (Owner is TComponent) then <------- This condition
makes Destroy to be called.
Destroy;
end;
I don't get why TRIO should destroy itself if its Owner isn't inherited from
TComponent. Anyone can try to explain it to me?
Best regards.
Michael Benford
 
 

Re:THHTPRIO component is freed after calling a remote method if it has no owner

Michael Benford skrev:
Quote

I don't get why TRIO should destroy itself if its Owner isn't inherited
from TComponent. Anyone can try to explain it to me?

Hi Michael
Anyone who knows more about this may correct me if I am wrong but I
believe it is due to the double nature of the RIO object. When created
in runtime it behaves as an Interface which is reference counted and
freed automatically when the refcount is 0, and when used as a component
it behaves as an object and is freed automatically by its owner.
regards
/Micke
 

Re:THHTPRIO component is freed after calling a remote method if it has no owner

Hello Mikael and Michael,
Yes, as Mikael described, the RIO has two lifetime-management styles. And
often this is the source of confusion: one forgets to explicitly nil the
interface retrieved from the RIO when it is used as a component (i.e. with
Parent not nil). In that scenario, when the interface is finally released
(Delphi invokes the Release() method behind the scene), the code causes a
crash because the underlying RIO object was destroyed by its parent
component.
In VCL most objects use one or the other approach. TInterfacedObject-derived
objects are refcounted while TComponent-based ones are managed by their
parent component. This dual approach used by the RIO is somewhat unusual but
it's very practical and comes in handy. I tend to use the component-based
approach when I have to quickly handle events [since the designer can
generate and bind my handlers]... and the interface-based one for other
cases.
The factory method generated by the importer [i.e. function Getxxxx - where
'xxxx' is the interface representing a WebService porttype] allows for both.
If you don't pass in a RIO, it uses a ref-counted one. If you have a
component-based one that you want to use, you pass it into the factory
method.
Cheers,
Bruneau.