Recent

Author Topic: Trying to check if object is Freed.  (Read 2639 times)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11485
  • Debugger - SynEdit - and more
    • wiki
Re: Trying to check if object is Freed.
« Reply #15 on: April 07, 2025, 07:15:29 am »
As for your problem, have a look at TRefCountedObject in LazUtils.

You need to add and remove references by hand. (i.e. always call AddReferenc or ReleaseReference whenever any instance is used).

And, you need to avoid circular references. As they will not be detected, and never be freed.
That may not be easy to achieve. You may need new classes that act as owners, and can't be owned.

There is also FreeNotifiyingObject in the same unit. So if you have backreferences, then you can use that, to make sure they get set to nil.

e.g. maybe
- a point can not own anything
- a line owns (adds references) to the points
- a surface adds references to all the lines it has
...

if a point knows about a line, then it adds a free notification. So when the Line is destroyed, it will send a notification and the point can remove it from its list.




EDIT:

Proper ownership design is a real important issue for bigger apps. Without it, never mind what you do, it will get complicated...

Btw, if you have a need where points need to know and (reference) lines, then maybe split point into the actual point, and a FooPoint that can own the point, and reference the line (but then will not be referenced by a line ever.

E.g. maybe you need to split your objects into
- the coordinate
- the actor that works with it
- user generated objects => hold explicitly user created stuff of any kind

Then within each of those groups you have a hierarchy ensuring no circles. But the outer actor group can own anything in the coordinate group. (coordinates never refer to actors).

 
« Last Edit: April 07, 2025, 08:20:28 am by Martin_fr »

mm7

  • Full Member
  • ***
  • Posts: 222
  • PDP-11 RSX Pascal, Turbo Pascal, Delphi, Lazarus
Re: Trying to check if object is Freed.
« Reply #16 on: April 07, 2025, 02:26:09 pm »
Thank you Martin, I'll check TRefCountedObject and FreeNotifiyingObject.
Though the ref model is complex, points refer to edges, and to faces,  and faces refer to edges, etc..., I believe I've made the ownership correctly. I checked it with memory tracer in past. Everything was good.
I just started thinking to turn global range and objects checks off to improve performance, and replace it with manual objects checks in critical places. That is where the idea of this function started. Also it was a good exercise to look under the hood of FPC.
Also you, folks, showed me things I was not aware of, new approaches, ideas. Thank you all.
I'll create separate case for Lazarus rebuild.

440bx

  • Hero Member
  • *****
  • Posts: 5595
Re: Trying to check if object is Freed.
« Reply #17 on: April 08, 2025, 12:18:23 am »
First a disclaimer: I don't know how FPC's memory manager works internally.

With the above out of the way, most memory managers keep track of free memory blocks.  It is conceivable to walk that list of free memory blocks and if a pointer happens to falls in an area that is in one of those blocks then, the block is free (obviously!)  Also, it is important to verify that the pointer is in the "global" block the MM is currently using, if it isn't there then the pointer might simply be an errant pointer.

The problem with that method is that it uses knowledge of the MM internals which makes it "fragile".
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

mm7

  • Full Member
  • ***
  • Posts: 222
  • PDP-11 RSX Pascal, Turbo Pascal, Delphi, Lazarus
Re: Trying to check if object is Freed.
« Reply #18 on: April 08, 2025, 01:57:44 am »
Try this (ignore the leak for b, that can be fixed):
Code: Pascal  [Select][+][-]
  1.     procedure TForm1.Button1Click(Sender: TObject);
  2.     var a,b: TStringList; i:integer;
  3.     begin
  4.       for i:=0 to 999999999 do
  5.       begin
  6.         a:= TStringList.create;
  7.         a.add('abc');
  8.         a.Destroy;
  9.         b:= TStringList.create;
  10.         if check_object(a,TStringList) then
  11.         begin
  12.            writeln('failure at ',i);
  13.            {$R+}
  14.            writeln(a.count); // FPC R$ check
  15.            {$R-}
  16.          end;
  17.       end;
  18.     end;
  19.  

Yes, no luck.  :(
Code: Pascal  [Select][+][-]
  1.     a:= TStringList.create;
  2.     a.add('abc');
  3.     a.Free;
  4.     b:= TStringList.create;
  5.     b.add('bbb');
  6.     b.add('bbb');
  7.     {$R+}
  8.     c := a.count; // FPC $R+ check is also fooled here! c will be set to 2 from object b.
  9.     {$R-}
  10.  


 

TinyPortal © 2005-2018