Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 07/07/24 in all areas

  1. JonRobertson

    How to debug a Not Responding program element

    Thanks Anders. This approach is should be used rather than the one I posted.
  2. JonRobertson

    How to debug a Not Responding program element

    TGadgetAnimations is a TObjectList that holds a list of TGadgetAnimation: TGadgetAnimations = class(TObjectList<TGadgetAnimation>) There are multiple instances of TGadetAnimations created here: constructor TGadgetMetaInfo.Create; var i: Integer; begin inherited; for i := 0 to ALIGNMENT_COUNT-1 do begin fVariableInfo[i].Animations := TGadgetAnimations.Create; The TObjectList.OwnsObjects property defaults to True and is not set to False for any instance of TGadgetAnimations. This means that TGadgetAnimations will call Free on the instances of TGadgetAnimation that it holds (which are added by the call to Add). The TObjectList.Clear method will remove all instances of TGadgetAnimation that were added to that instance of TGadgetAnimations. Since OwnsObjects is True, calling Clear will also call Free on each instance. When AddPrimary is called the first time for the instance, it assigns a reference to TGadgetAnimation to fPrimaryAnimation. procedure TGadgetAnimations.Clone(aSrc: TGadgetAnimations); var i: Integer; NewAnim: TGadgetAnimation; begin Clear; NewAnim := TGadgetAnimation.Create(aSrc.PrimaryAnimation.fMainObjectWidth, aSrc.PrimaryAnimation.fMainObjectHeight); NewAnim.Clone(aSrc.PrimaryAnimation); AddPrimary(NewAnim); <-- This will assign fPrimaryAnimation if it is not assigned. When Clone is called, it calls Clear, which frees the TGadgetAnimation instances that were previously created. But, it does not clear the fPrimaryAnimation reference, which is now pointing to unallocated memory. Use the solution posted by Anders of overriding the Notify method.
  3. Anders Melander

    How to debug a Not Responding program element

    Oh, I see... So TGadgetAnimations is in fact declared as derived from TObjectList<TGadgetAnimation>. This means that you can catch the destruction of a TGadgetAnimation by overriding the TObjectList<T>.Notify method: type TGadgetAnimations = class(TObjectList<TGadgetAnimation>) [...] protected procedure Notify(const Value: TGadgetAnimation; Action: TCollectionNotification); override; [...] end; procedure TGadgetAnimations.Notify(const Value: TGadgetAnimation; Action: TCollectionNotification); begin if (Action in [cnExtracting, cnDeleting]) and (Value = fPrimaryAnimation) then fPrimaryAnimation := nil; inherited; end; The call to Clear destroys all the objects contained in the list. The call stack shows you exactly how you got from TGadgetAnimations.Clear to TGadgetAnimation.Destroy.
×