[DUG] How's this for inconsistent
Todd
todd.martin.nz at gmail.com
Wed Nov 24 20:08:28 NZDT 2010
> Yep -- I remember that my fix was to set the "destructing" state
> indicator in a BeforeDestruction() override. This was then tested in
> _Release() to render it a NO-OP during execution of the destructor
> chain (incomplete, obviously, just to give the idea):
>
> Procedure BeforeDestruction;
>
> SetState(csDestroying);
>
> Function _Release;
>
> If csDestroying in State then EXIT;
>
Upon reflection, that would only work for a TComponent descendant.
>
> Nothing else needs be done, as long as any further BeforeDestruction
> overrides call inherited before doing their work, which they should do
> (in my framework I introduced another virtual to be overridden in my
> descendants, in case there were occasions when work was done to
> generate references during the destructor execution -- even in your
> case, the FreeInstance() override is redundant I think, other than as
> a sanity/safety check and so could be made subject to some conditional
> compilation flag.
>
> *From:* delphi-bounces at delphi.org.nz
> [mailto:delphi-bounces at delphi.org.nz] *On Behalf Of *Todd
> *Sent:* Wednesday, 24 November 2010 6:15 p.m.
> *To:* NZ Borland Developers Group - Delphi List
> *Subject:* Re: [DUG] How's this for inconsistent
>
> Actually, this would be better
>
> function TamObject._Release: Integer;
> begin
> Result := InterlockedDecrement(FCount);
> if (FCount = 0) then
> begin
> //add a reference count, incase an interface is acquired and
> released during destruction
> InterlockedIncrement(FCount);
> self.Destroy;
> end;
> end;
>
> procedure TamObject.FreeInstance;
> begin
> //remove the reference count added in _Release
> InterlockedDecrement(FCount);
> assert(FCount = 0,'Destroying object with non-zero reference count');
> inherited FreeInstance;
> end;
>
> 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.
>
> 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>
> [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 <mailto:delphi at delphi.org.nz>
> Admin:http://delphi.org.nz/mailman/listinfo/delphi
> Unsubscribe: send an email todelphi-request at delphi.org.nz <mailto:delphi-request at delphi.org.nz> with Subject: unsubscribe
>
>
> _______________________________________________
> 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/17d6f9e3/attachment-0001.html
More information about the Delphi
mailing list