Destroying COM object in Delphi
Have some .ne开发者_StackOverflowt assembly, calling it in delphi through COM.
var
intf: ITest;
...
intf:= CreateComObject(CLASS_TEST) as ITest;
...
//here comes some stuff
...
Must i do something to destruct it to free memory. Or not?
COM objects are reference-counted, and they get automatically destroyed when the reference count reaches zero. The compiler will automatically add calls to _AddRef
and _Release
interface methods whenever your code adds a reference to the object or removes it. Setting a variable referencing a COM object to nil
will call _Release
(decrementing the reference count), and if the reference count reaches zero the object is also freed (it won't be if the reference count is not zero). When a variable goes out of scope (i.e. a local variable, when the procedure exits), the compiler will also call _Release
if the variable references a COM object (or any reference-counted Delphi interface).
All COM interfaces must implement IUnknown
:
IUnknown = interface
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
IUnknown
provides two services. First of all, QueryInterface
allows for clients to obtain the other interfaces that the object may implement. The second service is that of lifetime management.
Every time you take a reference to a COM object it is your responsibility to call _AddRef
. Every time you give up a reference to a COM object, you are contracted to call _Release
.
The canonical implementation of _AddRef
and _Release
is for the implementing object to maintain a reference count variable which is incremented and decremented as references are taken and released. If a call to _Release
sets this reference count to 0 then the object destroys itself.
The Delphi implementation of interfaces manages the calls to _AddRef
and _Release
on your behalf. When you assign to an interface variable the compiler emits code that:
- Calls
_Release
on the interface that the variable previously referred to, if indeed it did previously refer to something. - Calls
_AddRef
on the interface that the variable now refers to.
The compiler also arranges for _Release
to be called whenever the variable leaves scope.
What this means is that you need to take no special action whatsoever to ensure that your COM objects will be destroyed. They will naturally be destroyed when the last reference to the object leaves scope.
If however, you do wish to destroy an object ahead of time, then you simply assign nil
to the variable holding the interface. Note that this is of course presuming that no other references are held to that interface.
You should better release the memory with
intf := nil;
When you don't need it any more. Better with a try...finally intf := nil;
block, or in the Destroy
overriden method if intf
is defined as fIntf
, i.e. as a class property.
If intf
is defined on stack, it will we freed automatically at the end of the method. There is an hidden try...finally intf := nil; end
block generated by the compiler to free the intf
instance.
The object is released automatically. However, if you explicitly want to release the reference that the intf
variable holds, you can set it to nil.
精彩评论