Ausgabe von Komponenten-Inhalten

Für Fragen rund um die Ide und zum Debugger
Antworten
Ronny58
Beiträge: 73
Registriert: So 27. Apr 2014, 20:35

Ausgabe von Komponenten-Inhalten

Beitrag von Ronny58 »

Wenn ich in beim Debuggen meine Programms mit der Maus über eine Variable gehen, wird mir dessen Inhalt in einem gelben Hint-Fenster angezeigt. Soweit so gut. Mach ich das bei einer Komponente, bekomme ich dies nicht.

Vereinfachtes Beispiel: eine Komponente "edName" vom Typ TEdit: edName.Caption := 'Hallo';

Behauptet mir der Debugger immer (in dem gelben Hint-Fenster);
"edName.Caption = TYPE TEDIT has no Component named Caption"

Ich habe mir bisher geholfen in einem solchen Fall mir eine Variable vom Typ String anzulegen, dort den Wert zu abzulegen, damit ich mir den Inhalt anschauen kann, der dem Caption zugewiesen wird. Das Problem betrifft absolut alle Komponenten, die ich benutze.

Debugger: $(LazarusDir)\mingw\$(TargetCPU)-$(TargetOS)\bin\gdb.exe

Gibt da irgendwo einen Schalter, den ich setzen muss, damit ich den Inhalt von Caption im Hint-Fenster sehe sehe?

Ich weis, dass ich das früher mal konnte. Seit meiner Neuinstallation Version 2.0.6 Datum 30.03.2020 FPC 3.0.4 SNV 62192 geht das nicht mehr.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 667
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Ausgabe von Komponenten-Inhalten

Beitrag von fliegermichl »

Der Debugger kann keine Inhalte von Properties anzeigen die eine Getter Methode haben. Das ist schon sehr traurig. Mein altes Delphi 5 von 1998 kann das problemlos.

PascalDragon
Beiträge: 91
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Ausgabe von Komponenten-Inhalten

Beitrag von PascalDragon »

fliegermichl hat geschrieben:
Fr 18. Sep 2020, 08:51
Der Debugger kann keine Inhalte von Properties anzeigen die eine Getter Methode haben. Das ist schon sehr traurig. Mein altes Delphi 5 von 1998 kann das problemlos.
Martin Friebe (welcher unter anderem an der Schnittstelle für GDB in Lazarus arbeitet) hat vor ein paar Monaten mal ausführlich erklärt warum das der Fall ist, ich finde jedoch den Beitrag nicht mehr (ganz davon abgesehen, dass ich nicht einmal mehr weiß, ob es hier, im englischen Forum, im Bugtracker oder auf einer der Mailing Listen war).

Kurz zusammen gefasst:
  • Die Debuginformation von FPC ist noch nicht vollständig genug, so dass dies korrekt ausgewertet werden könnte
  • Der Debugger muss im Grunde einen Funktionsaufruf durchführen, dazu muss der passende Kontext inklusive Stack angelegt werden (GDB kann das im Grunde, aber das heißt nicht, dass da nicht noch einiges an Handarbeit ist)
  • Dann muss sichergestellt werden, dass ein Getter der nicht so handzam ist, nicht alles hängen lässt
  • Außerdem ist zu beachten, dass der Aufruf eines Getters auch den Zustand eines Programms ändern kann (zum Beispiel Lazy Initialization von Feldern)
Bei alledem darfst du nicht vergessen, dass FPC und Lazarus Hobbyprojekte sind und wir noch dazu auf 3rd Party Anwendungen (GDB, wobei es hier mit fpDebug eine Pascal-basierte Alternative gibt) und Spezifikationen (DWARF) angewiesen sind. Delphi andererseits hatte für diese Entwicklung Vollzeitentwickler und auch alles komplett unter deren Kontrolle.
FPC Compiler Entwickler

Ronny58
Beiträge: 73
Registriert: So 27. Apr 2014, 20:35

Re: Ausgabe von Komponenten-Inhalten

Beitrag von Ronny58 »

Ok. Dann ist nicht falsch bei mir eingestellt.
Mann kann sich ja mit Dummy-Variablen behelfen. Man darf nur nicht vergessen sie wieder aufzuräumen.
Der Compiler hilft ja außerdem beim Aufräumen ungenutzter Variablen.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 667
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Ausgabe von Komponenten-Inhalten

Beitrag von fliegermichl »

Ich wollte auf keinen Fall FPC oder Lazarus schlecht machen - im Gegenteil.
Das für das auslesen von Properties mit Getter Methoden Funktionsaufrufe stattfinden müssen ist klar.
Auch in Delphi muß ich dafür extra eine Option aktivieren.

Wenn ich für Lazarus bzw. FPC einen Wunsch abgeben könnte, wäre für mich dieser Punkt der mit der höchsten Priorität.

Ich habe allerhöchsten Respekt für die Entwickler von Lazarus und FPC eben weil es Hobbyprojekte sind.

charlytango
Beiträge: 203
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: Ausgabe von Komponenten-Inhalten

Beitrag von charlytango »

oder für debug-Zwecke gleich mit bedingter Kompilierung arbeiten

Code: Alles auswählen

{$IFDEF DEBUG}
  MyDummy:=125;
{$ENDIF}
https://wiki.freepascal.org/Conditional_compilation[url]
[/url]

Benutzeravatar
theo
Beiträge: 8471
Registriert: Mo 11. Sep 2006, 19:01

Re: Ausgabe von Komponenten-Inhalten

Beitrag von theo »

Richtige Männer brauchen keine Debugger! :mrgreen:

SCNR

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2304
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.8, FPC 3.0.4)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Ausgabe von Komponenten-Inhalten

Beitrag von m.fuchs »

Du kannst dir auch häufig den Umweg über eine temporäre Variable ersparen.
Mit Strg+Alt+W kannst du das Fenster für überwachte Ausdrücke aufrufen. Dort fügst du einen neuen hinzu und benutzt dabei nicht die Property sondern das dahinterliegende Feld, welches die Daten enthält. Für die Caption eines Buttons wäre der gesuchte Ausdruck dann Button1.FCaption. Wenn du nun mit dem Debugger durchstepst, dann siehst du im Fenster immer den aktuellen Wert.

Bild

Wie kommt man an diesen Feldnamen?
  1. Raten: Bei der Property Caption lautet der Feldname vermutlich FCaption. Bei Color ist es FColor und so weiter.
  2. Nachschauen: Man sieht sich im Quellcode die Deklaration der Property an.

    Code: Alles auswählen

    property Color: TColor read FColor write SetColor stored ColorIsStored default {$ifdef UseCLDefault}clDefault{$else}clWindow{$endif};
    property Caption: TCaption read GetText write SetText stored IsCaptionStored;
Bei Color werden die Daten aus FColor gelesen, ein Sprung dahin sagt uns dass es eine Variable vom Typ TColor ist. Wir haben das Feld also gefunden.
Bei Caption wird GetText bemüht zum Lesen der Daten. Und die sieht so aus:

Code: Alles auswählen

function TControl.GetText: TCaption;
var
  len: Integer;
  GetTextMethod: TMethod;
begin
  // Check if GetTextBuf is overridden, otherwise we can call RealGetText directly
  Assert(Assigned(@Self.GetTextBuf), 'TControl.GetText: GetTextBuf Method is Nil');
  GetTextMethod := TMethod(@Self.GetTextBuf);
  if GetTextMethod.Code = Pointer(@TControl.GetTextBuf) then begin
    Result := RealGetText;
  end
  else begin
    // Bummer, we have to do it the compatible way.
    DebugLn('Note: GetTextBuf is overridden for: ', Classname);
    len := GetTextLen;
    if len = 0 then begin
      Result := '';
    end
    else begin
      SetLength(Result, len+1); // make sure there is room for the extra #0
      FillChar(Result[1], len, #0);
      len := GetTextBuf(@Result[1], len+1); 
      SetLength(Result, len);
    end;
  end;
end; 
Das sieht natürlich weniger schön aus. Mit ein bisschen Suchen finden wir in der 10. Zeile, dass (im Standardfall) RealGetText aufgerufen wird. Die sieht schon etwas übersichtlicher aus:

Code: Alles auswählen

function TControl.RealGetText: TCaption;
begin
  Result := FCaption;
end; 
Das Daten für die Property stehen also in FCaption.


Warum ist das alles so umständlich und warum kann der Debugger nicht einfach GetText aufrufen?
Das liegt an der Gefahr einen Seiteneffekt auszulösen:

Code: Alles auswählen

function TWatchButton.GetCaption: String;
begin
  ReadCount := ReadCount + 1;
  Result := FCaption;
end;
Dieser Getter inkrementiert bei jeden Aufruf einen Counter um die Anzahl der Getter-Aufrufe zu loggen. Jedesmal wenn der Debugger die zugehörige Property zugreift, würde das auch passieren. Damit ist der Wert in ReadCount höher als ohne Debuggereinsatz, das Programm verhält sich also mit Debugger anders als ohne. Das sollte man möglichst vermeiden.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 667
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Ausgabe von Komponenten-Inhalten

Beitrag von fliegermichl »

m.fuchs hat geschrieben:
Fr 18. Sep 2020, 12:00

Warum ist das alles so umständlich und warum kann der Debugger nicht einfach GetText aufrufen?
Das liegt an der Gefahr einen Seiteneffekt auszulösen:

Dieser Getter inkrementiert bei jeden Aufruf einen Counter um die Anzahl der Getter-Aufrufe zu loggen. Jedesmal wenn der Debugger die zugehörige Property zugreift, würde das auch passieren. Damit ist der Wert in ReadCount höher als ohne Debuggereinsatz, das Programm verhält sich also mit Debugger anders als ohne. Das sollte man möglichst vermeiden.
Deswegen muß ich auch in Delphi erst die Option "Funktionsaufrufe erlauben" aktivieren.
Solche Nebeneffekte werden sicher seltener auftreten als das sich der Programmierer den Inhalt von Properties mit Getter Methoden anschauen möchte.

Mathias
Beiträge: 5084
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ausgabe von Komponenten-Inhalten

Beitrag von Mathias »

theo hat geschrieben:
Fr 18. Sep 2020, 11:34
Richtige Männer brauchen keine Debugger! :mrgreen:

SCNR
Da hast du recht. :mrgreen:
Ich weis nicht mal wie dies geht. 8)

Ich brauche viel ShowMessage() und Writeln().
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2304
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.8, FPC 3.0.4)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Ausgabe von Komponenten-Inhalten

Beitrag von m.fuchs »

fliegermichl hat geschrieben:
Fr 18. Sep 2020, 13:55
Deswegen muß ich auch in Delphi erst die Option "Funktionsaufrufe erlauben" aktivieren.
Das ist dann schon einmal besser als im Visual Studio, dort macht der Debugger das immer.
fliegermichl hat geschrieben:
Fr 18. Sep 2020, 13:55
Solche Nebeneffekte werden sicher seltener auftreten als das sich der Programmierer den Inhalt von Properties mit Getter Methoden anschauen möchte.
Ich würde es anders herum sehen. In den meisten Fällen nutzt eine Property nur für den Setter eine Methode. Man will ja häufig den übergebenen Wert verifizieren oder beim Ändern von Werten eine Aktion auslösen. Der Getter zeigt dann einfach nur auf das Feld.
Es wird also eher seltener Auftreten, dass man sich tatsächlich die Getter-Methode ansehen muss. Wenn es aber eine gibt, dann sollte man auch reinsehen und nicht den Debugger das Ding automagisch auswerten lassen.

Ist wie beim Experimentieren. Wenn die Messwerte meines Experiments nicht den Erwartungen entsprechen, sollte ich erst einmal prüfen ob ich richtig messe.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2304
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.8, FPC 3.0.4)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Ausgabe von Komponenten-Inhalten

Beitrag von m.fuchs »

theo hat geschrieben:
Fr 18. Sep 2020, 11:34
Richtige Männer brauchen keine Debugger! :mrgreen:
Das stimmt, der Einsatz eines Debuggers zeigt einem häufig dass irgendwo ein Unit-Test vergessen wurde. :D
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten