0

I'm using Delphi 10.2. I'm having a problem calling TList<>.Last. The Evaluate window tells me the code for the function has been eliminated by the linker.

The code snippets:

uses
    ModelObjects,
    ProximitySearch,
    System.Classes,
    System.UITypes,
    System.Generics.Collections,
    Winsoft.FireMonkey.FPdfView,
    Winsoft.FireMonkey.PDFium;
...

type
    TWidgetFinder = class(TObject)
private
        fFieldInfos: TList<TFieldInfo>;
        fPAnnotation: FPDF_ANNOTATION;
...

procedure TWidgetFinder.ConfigureFieldInfo;
var
    key: String;
    buffer: TBytes;
    textLen: LongWord;
    temp: String;
begin
...
    SetLength(buffer, KShortBufferLength);
    textLen := FPDFAnnot_GetStringValue(fPAnnotation, ToStringType(key), buffer, Length(buffer))
    temp := TEncoding.Unicode.GetString(buffer, 0, textLen - 2);
    fFieldInfos.Last.Name := TEncoding.Unicode.GetString(buffer, 0, textLen - 2);
...

The problem was fFieldInfos.Last.Name was empty. I thought I was not converting the buffer to a string correctly. But the correct string is written to temp. When I Evaluate fFieldInfos.Last.Name after assigning to it I get the following message:

Function to be called, {System.Generics.Collections}TList<ModelObjects.TFieldInfo>.Last, was eliminated by linker

I've seen the SO solutions that suggest I call the eliminated function innocuously during initialization. But it cannot be that Delphi is eliminating code randomly and I must discover each elimination as a bug. I don't understand what I have done that tells the linker TList<>.Last is not being used when I am clearly using it. Can someone help me understand this?

Thanks

David U
  • 943
  • 1
  • 8
  • 22
  • 4
    It's a debugger issue. The code is fine. Nothing has been eliminated that should not have been. – David Heffernan Nov 16 '18 at 22:00
  • If that part of your code perhaps inside some conditional clause or a loop? – SilverWarior Nov 17 '18 at 00:26
  • 1
    The actual code is eliminated by the linker. Loops and variables might have changed to use a register, functions may have been inlined, and so on... Because of that, the debugger cannot find it anymore, but the actual _functionality_ is still there. If this is giving you trouble while debugging, go to Project -> Options -> Compiling and, make sure to uncheck 'Optimization'. – GolezTrol Nov 17 '18 at 10:29
  • Possible duplicate of [Delphi 2009 Function eliminated by linker](https://stackoverflow.com/questions/12748105/delphi-2009-function-eliminated-by-linker) – GolezTrol Nov 17 '18 at 10:31
  • Also related (maybe more, because generics): [GetItem on TDictionary eleminated by linker](https://stackoverflow.com/questions/15290943/getitem-on-tdictionary-eleminated-by-linker) – GolezTrol Nov 17 '18 at 10:32
  • 1
    It did not seem productive to try and blame an error on optimization. David Heffernan’s comment reminded me that I had seen eliminated code running in Delphi’s debugger once many years ago. So I took him at his word, decided to believe the function is actually present, and moved on. The code appears to be working now. Thank you for your help. – David U Nov 18 '18 at 00:14

1 Answers1

2

TList<T>.Last is a function marked as inline. Such methods usually are not contained in the binary so you cannot use them in the evaluator during debugging. The same is the case most likely if you type fFieldInfos[fFieldInfos.Count-1] because GetItem (the getter behind the index property) is marked as inline as well.

What you can type into the evaluator though is fFieldInfos.List[fFieldInfos.Count-1] to get the last item in the list.

P.S. As for the issue of Name being empty - if TFieldInfo is a record that assignment is not going to work because .Last will return a copy of that record and assign Name to that one not affecting the one inside the list.

Kromster
  • 7,181
  • 7
  • 63
  • 111
Stefan Glienke
  • 20,860
  • 2
  • 48
  • 102