Search code examples
delphiweak-referencesweak-ptrdangling-pointer

Dangling pointer in Delphi


I'm not using interfaces (so the objects has no reference counting). The objects may be referenced by many others, and i need to deal with the dangling pointers. FreeAndNil() doesn't solves the problem for multiple references. I need that when an object is destroyed all the pointers that references to it are setted to nil automatically. Alternatively it could be something like the Expired() method of std::weak_ptr in C++.

I could implement a "weak-smart pointer" to do this, but i'm not sure if it is an over-complicated implementation. Do you suggest another solution?. This is the untested possible solution that i'm thinking:

type
  TWeakReferenceable = class
  constructor Create();
  destructor  Destroy(); override;  //Set ReferencedObject:=nil for all the weak references in FWeakReferenceList
  private
    FWeakReferenceList: TList; //List of weak references to this object
  protected
    procedure RegisterWeakReference(const AWeakReference: TWeakReference<TWeakReferenceable>);   //Adds a weak reference 
    procedure UnregisterWeakReference(const AWeakReference: TWeakReference<TWeakReferenceable>);   //Removes a weak reference
  end;

type
  TWeakReference<TObjectType: TWeakReferenceable> = class
  constructor Create();
  destructor  Destroy(); override; //Destroys the object and calls UnregisterWeakReference(self) for the referenced object 
  private
    FObjectReference: TObjectType;
    procedure SetReference(AReferencedObject: TObjectType); //Calls UnregisterWeakReference(self) for the current reference, updates FObjectReference and calls RegisterWeakReference(self) for the referenced object  
  public
    property  ReferencedObject: TObjectType read FObjectReference write SetReference;
  end; 

Solution

  • For mobile platforms, Delphi uses ARC (automatic reference counting) for objects, and the compiler has a [weak] attribute for declaring a weak pointer that gets nilled automatically when the referenced object is freed.

    For desktop platforms, Delphi does not use ARC for objects. However, TComponent has its own mechanism for handling "weak" references - its FreeNotification() method. When a component is interested in another component's lifetime, it has to call the other component's FreeNotification() method. TComponent maintains an internal list of interested components. When a TComponent object is freed, it calls the Notication() method of those interested components so they can nil their references to the component being freed.

    The code you showed is not using TComponent, though. So you would have to create your own registration/notification system to nil your references to freed objects.