[DUG] How's this for inconsistent
Todd
todd.martin.nz at gmail.com
Wed Nov 24 17:38:05 NZDT 2010
Hi Jolyon
>
> I spotted that they fixed that a while ago -- I remember having to fix
> the issue myself many years ago so was quite pleased to see that it
> was now taken care of in TInterfaceObject as a matter of course. For
> some reason I never noticed the omission of the same facility in the
> destructor. And yes, it's a [potentially] big problem.
>
> I need to think about this tho... setting a fake ref count during
> execution of the constructor is safe enough as you know precisely when
> construction is done and to restore the ref count back to zero.
>
> Setting a fake ref count during destruction strikes me as more
> problematic and makes me nervous, but I can't quite put my finger on
> why. It might be nothing. That doesn't mean it can't be fixed, only
> that the solution put in place for construction might not work for
> destruction and it wasn't felt necessary to do any extra work for a
> more comprehensive solution.
>
>
I fixed it like this
procedure TamObject.BeforeDestruction;
begin
//add a reference count, in case an interface is acquired and
released during destruction
InterlockedIncrement(FCount);
inherited BeforeDestruction;
end;
procedure TamObject.FreeInstance;
begin
//remove the reference count added in BeforeDestruction
InterlockedDecrement(FCount);
assert(FCount = 0,'Destroying object with non-zero reference count');
inherited FreeInstance;
end;
Of course, an interface can still not be referenced in descendant
BeforeDestruction methods, (since the inherited method is usually called
at the end), but can be safely referenced in the destructor.
Todd.
>
> Certainly in the case of my code where I fixed this I had specific
> "constructing" / "destructing" state markers (it wasn't a general
> purpose interfacedobject class but a base class in a far richer
> framework that happened to also implement its own version of IUnknown)
> -- I know I didn't rely on side effects of a faked ref count.
>
> *From:* delphi-bounces at delphi.org.nz
> [mailto:delphi-bounces at delphi.org.nz] *On Behalf Of *Todd
> *Sent:* Wednesday, 24 November 2010 16:55
> *To:* NZ Borland Developers Group - Delphi List
> *Subject:* [DUG] How's this for inconsistent
>
> The Delphi developer who implemented TInterfacedObject obviously
> considered the case when an interface reference is grabbed during
> construction......
>
> // Set an implicit refcount so that refcounting
> // during construction won't destroy the object.
> class function TInterfacedObject.NewInstance: TObject;
> begin
> Result := inherited NewInstance;
> TInterfacedObject(Result).FRefCount := 1;
> end;
>
> procedure TInterfacedObject.AfterConstruction;
> begin
> // Release the constructor's implicit refcount
> InterlockedDecrement(FRefCount);
> end;
>
> but didn't consider applying the same logic during destruction. So
> grabing an interface reference during destruction causes all hell to
> break loose, as the _Release method tries to free the object again and
> again recursively.
>
> procedure TInterfacedObject.BeforeDestruction;
> begin
> if RefCount <> 0 then
> Error(reInvalidPtr);
> end;
>
> function TInterfacedObject._Release: Integer;
> begin
> Result := InterlockedDecrement(FRefCount);
> if Result = 0 then
> Destroy;
> end;
>
> Todd.
>
>
> _______________________________________________
> NZ Borland Developers Group - Delphi mailing list
> Post: delphi at delphi.org.nz
> Admin: http://delphi.org.nz/mailman/listinfo/delphi
> Unsubscribe: send an email to delphi-request at delphi.org.nz with Subject: unsubscribe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://listserver.123.net.nz/pipermail/delphi/attachments/20101124/7a79988b/attachment.html
More information about the Delphi
mailing list