Recent

Author Topic: Memory leak: setting TCustomSynEdit.Text doesn't free ranges  (Read 4632 times)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« on: September 27, 2016, 09:36:26 pm »
Martin,

i often use TCustomSynEdit.Text to initialize the Text of a SynEdit. When there was a text before it's ranges do not get freed
(mem leak). I know that the Text property isn't recognized for undo and so on but it will be easy to make Text use TextBetween
instead of FLines.Text. What do you think about this enhancement?

Pascal
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« Reply #1 on: September 27, 2016, 10:19:36 pm »
.Text would be used if an editor opens a new file. So there would be no undo info needed, in fact not wanted.

Keeping undo info could break existing apps. (undo after open, and you have another files content, but under the new filename)

About ranges not freed: Do you mean the range list, or the actual range objects.

the actual range object is indeed never freed (by design / as designed in SynEdit long ago).
They are (or should) never be entirely lost. They should always be kept reachable, and being reused, as many of them will be needed again, if a new text is loaded.

IMHO not the best design, and needs to be fixed. But it is a rather large refactor.


Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« Reply #2 on: September 27, 2016, 10:39:27 pm »
Just had a look, there may be (but I havent looked enough to confirm) some issues.

When ranges are detached, they may not free all the should.

TSynCustomHighlighter.DetachFromLines
calling  r.Free // r: TSynHighlighterRangeList;

That should free the ranges from a first look....

Yet the IDE does all that, and there are no leaks.

------------------
Also I am not sure if there are several HL of the same class, if they share ranges, as they should.


You may report that, probably a while before I can look at it.

--- Edit
I looked the wrong place.
They are destroyed in TSynCustomHighlighterRanges.Destroy.

And through that they are also shared.
« Last Edit: September 27, 2016, 10:55:45 pm by Martin_fr »

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« Reply #3 on: September 28, 2016, 06:25:08 am »
I have build a COBOL-Highlighter based on TSynCustomFoldHighlighter.

I overwrote the following procedures/functions:
Code: Pascal  [Select][+][-]
  1. function TprimeEditHighlighterCobol.CreateRangeList(ALines: TSynEditStringsBase): TSynHighlighterRangeList;
  2. begin
  3.   Result := TprimeHighlighterCobolRangeList.Create;
  4. end;
  5.  
  6. procedure TprimeEditHighlighterCobol.ResetRange;
  7. begin
  8.   inherited ResetRange;
  9.   fRange := rsUnknown;
  10. end;
  11.  
  12. procedure TprimeEditHighlighterCobol.SetRange(Value: Pointer);
  13. begin
  14.   // must call the SetRange in TSynCustomFoldHighlighter
  15.   inherited SetRange(Value);
  16.   fRange := TRangeState(PtrInt(CodeFoldRange.RangeType));
  17.   //fRange := TRangeState(CodeFoldRange.RangeType);
  18. end;
  19.  
  20. function TprimeEditHighlighterCobol.GetRange: Pointer;
  21. begin
  22.   // Store the range first
  23.   CodeFoldRange.RangeType := Pointer(PtrInt(fRange));
  24.   Result := inherited GetRange;
  25.   //fRange := (Result).Range;
  26. end;
  27.  

TprimeHighlighterCobolRangeList does not get destroyed when i assign Text on loading files.

Have i missed to override one function/procedure?
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« Reply #4 on: September 28, 2016, 02:08:31 pm »
In should not get destroyed if you assign text. (After all the new text will be highlighted too.)

It should be (from memory / need to check) destroyed if you do
SynEdit.Highlighter := nil; (or any other HL)

If your HL is assigned to more than one SynEdit, you must do this for all of them, as there will be one list per SynEdit.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« Reply #5 on: September 28, 2016, 09:35:22 pm »
I've overridden the Text property for my SynEdit class:

Code: Pascal  [Select][+][-]
  1. procedure TprimeBaseEdit.primeSetText(AValue: string);
  2. begin
  3.   TextBetweenPoints[Point(1,1), Point(Length(Lines[lines.Count - 1]) + 1, Lines.Count)] := AValue;
  4.   ClearUndo;
  5. end;
  6.  

But if i assign text throug the Text property and close the program still line 1 doesn't get freed!

Known from nternal debuging list of all created TprimeCobolRangeInfo:
Code: Pascal  [Select][+][-]
  1. var
  2.   gprimeCobolRangeInfoCount: Integer;
  3.   gCobolRangeInfoList: TList;
  4.   gCobolRangeInfo: TprimeCobolRangeInfo;
  5.  
  6.   ...
  7.  
  8. constructor TprimeCobolRangeInfo.Create;
  9. begin
  10.   inherited Create;
  11.   ...
  12.   if Self.ClassType = TprimeCobolRangeInfo then begin
  13.     gCobolRangeInfoList.Add(self);
  14.     inc(gprimeCobolRangeInfoCount);
  15.   end;
  16. end;
  17.  
  18. ...
  19.  
  20. destructor TprimeCobolRangeInfo.Destroy;
  21. begin
  22.   ...
  23.   inherited Destroy;
  24.   if Self.ClassType = TprimeCobolRangeInfo then begin
  25.     gCobolRangeInfoList.Remove(self);
  26.     dec(gprimeCobolRangeInfoCount);
  27.   end;
  28. end;
  29.  
  30. ...
  31.  
  32. initialization
  33.   gCobolRangeInfoList := TList.Create;
  34.   gprimeCobolRangeInfoCount := 0;
  35.   MakeIdentTable;
  36.   RegisterPlaceableHighlighter(TprimeEditHighlighterCobol);
  37.  
  38. finalization
  39.  
  40.   if gprimeCobolRangeInfoCount > 0 then begin
  41.     while gCobolRangeInfoList.Count > 0 do begin
  42.       gCobolRangeInfo := TprimeCobolRangeInfo(gCobolRangeInfoList.Last);
  43.       DebugLn('  CobolRangeInfo: %s: %s', [gCobolRangeInfo.fFile, gCobolRangeInfo.fText]);
  44.       gCobolRangeInfoList.Remove(gCobolRangeInfo);
  45.       gCobolRangeInfo.Free;
  46.     end;
  47.   end;
  48.   gCobolRangeInfoList.Free;
  49. end.

If i set the Highlihter to nil, use (original) Text property and then set Highlighter back to original it works as expected.

Strange, isn't it.

laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: Memory leak: setting TCustomSynEdit.Text doesn't free ranges
« Reply #6 on: September 29, 2016, 01:20:49 am »
Now you are looking at 2 individual things.

Yes, Line 1 never gets deleted. It must always exist.
Well a new SynEdit does not have it in the lines object. But it behaves as if it exists. Caret is at (1,1).

That has nothing todo with the ranges / range-list. Neither will be destroyed, not even if you manage to delete the last line.

As I said the range-list will exist as long as the HL is attached to the SynEdit.
It gets created on attach, even if SynEdit has no text at the time. So detach is the correct place to remove it.

I do not know what TprimeCobolRangeInfo is / inherits from...

Individual ranges only get destroyed if the HL is destroyed. Otherwise they are kept, and re-used at some time. (as I said, this part of the design is not the best, I have ideas, that need to be tested, and might improve this. But it will be huge work / not now)

Ranges are not kept on the TprimeHighlighterCobolRangeList / TSynHighlighterRangeList.
Those only keep references (and many lines often refer to the same range).
Ranges are on "fRanges: TSynCustomHighlighterRanges;"

Just to say: keep in mind that ranges, once added to fRanges, are immutable.

 

TinyPortal © 2005-2018