[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