Debugging

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Debugging

Beitrag von charlytango »

Hi,

in einer Applikation mit etlichen Formularen samt DB-Anbindung verhalten sich die Formulare "normalerweise" wie gewünscht.
Unter bestimmten Umständen gibt es beim Schließen der Applikation und damit dem Schließen offener Formulare eine Exception in TZAbstractRODataset.GetRecordCount weil offensichtlich zu diesem Zeitpunkt (Operation cannot be performed on an inactive dataset) ein Datenset nicht aktiv ist.

So weit so nachvollziehbar. Bloß finde ich dieses sch..öne Datenset nicht.

Jetzt hab ich schon etliche Zeit investiert auf der Jagd nach diesem offenen Datenset. Durchsteppen, Breakpoints etc. hab ich schon durch -- vermutlich aber nicht am richtigen Ort oder zur richtigen Zeit. Scheinbar sind meine Debuggingfähigkeiten noch immer mangelhaft.

Nach der Exception steht der Code bei TZAbstractRODataset.GetRecordCount -- eigentlich müsste ich "nur" wissen welches Codestück diese Funktion aufgerufen hat, leider bin ich da mit meinem Latein am Ende.
Auch über CheckActive in der Funktion GetRecordCount bekomme ich nix über das betroffene Datenset heraus.

Gibt es eine Methode etwa den Callstack zu befragen oder herauszubekommen wie das betroffene Datenset heißt ?

Bin für sachdienliche Hinweise zur Ergreifung des Bugs dankbar ;)

Danke im Voraus

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Debugging

Beitrag von Michl »

Der GDB arbeitet bei mir (Windows 7, Lazarus 32bit) am besten mit Dwarf2 Debugsymbolen (-gw2). In der IDE kannst du dir mit <Strg> + <Alt> + <S> den Aufrufstack anzeigen lassen. Weitere Infos: http://wiki.lazarus.freepascal.org/GDB_Debugger_Tips

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Debugging

Beitrag von charlytango »

Michl hat geschrieben:Der GDB arbeitet bei mir (Windows 7, Lazarus 32bit) am besten mit Dwarf2 Debugsymbolen (-gw2). In der IDE kannst du dir mit <Strg> + <Alt> + <S> den Aufrufstack anzeigen lassen. Weitere Infos: http://wiki.lazarus.freepascal.org/GDB_Debugger_Tips



Danke erstmal, aber irgendwie komm ich auch damit nicht weiter.
mittlerweile vermute ich dass der auf dem Form befindliche DB-Grid für den RecordCount-Aufruf zuständig ist, um die Größe der Scroll-Leisten zu berechnen.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Debugging

Beitrag von af0815 »

Was siehst du im Aufrufstack (wie oben beschrieben) wenn der Fehler auftritt ? Hinweis, ev. muss man auf Max. 50 umschalten, damit man sieht wo das herkommt. Kannst ja auch den Inhalt mit 'alle kopieren' mal hier hereinstellen.

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Debugging

Beitrag von wp_xyz »

Dann hier eine Schnellanleitung, wie man mit dem CallStack arbeitet:

Hier ist ein Programm (einfaches Formulat mit einem Button), das eine Exception beim Klick auf den Button erzeugt (weil in der Anweisung "Format()" ein Platzhalter für einen Integer verwendet wird, als Parameter aber ein String übergeben ist).

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    function BuildMsg: String;
    procedure DisplayMessage;
 
  public
 
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
function TForm1.BuildMsg: String;
begin
  Result := Format('String mit falschem Platzhalter %d', ['Hallo']);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  DisplayMessage;
end;
 
procedure TForm1.DisplayMessage;
var
  s: String;
begin
  s := BuildMsg;
  ShowMessage(s);
end;
 
end.
 


Wenn du dieses Programm laufen lässt und nach dem Click auf den Button die Exception erzeugt wird, klickst du in der Meldungsbox der Exception auf "Anhalten" und öffnest das Fenster des Aufruf-Stacks - Tastenkombinationen sind wegen der Konfigurierbarkeit etwas problematisch, aber sicher geht's mit "Ansicht" > "Debugger-Fenster" > "Aufrufstack". Der sieht bei diesem Programm zu diesem Zeitpunkt so aus wie in dem Screenshot. Ganz oben steht die Routine, die die Exception ausgelöst hat - das ist irgend eine Routine im FPC-Code. Nach unten siehst du diejenigen Routinen, die jeweils die darüberstehende aufgerufen haben. Wenn du also von oben nach unten gehst, stößt du in der Zeile mit der Nr 5 auf die Funktion "TFORM1_BUILDMSG...", Zeile 36. Das ist die letzte Zeile aus dem eigenen Code, als es zum Fehler gekommen ist. Gehe zu dieser Zeile, und du bist an der Fehlerursache. Manchmal wird allerdings der Fehler weiter außen angelegt. In diesem fall musst du natürlich auch die darunterstehenden Zeilen prüfen.
Dateianhänge
CallStack.png

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Debugging

Beitrag von Michl »

wp_xyz hat geschrieben:Manchmal wird allerdings der Fehler weiter außen angelegt. In diesem fall musst du natürlich auch die darunterstehenden Zeilen prüfen.
Falls der Debugger bzw. die Debugsymbole nicht richtig eingestellt sind, kann es auch passieren, daß Haltepunkte nicht angesprungen werden - das darf nicht sein. Daher der Hinweis mit Dwarf2, siehe oben. Soweit ich mich richtig erinnere, ist das unter Linux GTK2 auch so.

@OP: Das CallStack-Window ist bei mir immer geöffnet. Dank AnchorDocking ist das Ganze auch sehr übersichtlich. Ohne die richtigen Debug-Projekteinstellungen und ohne Auswertung des CallStacks wäre ich echt aufgeschmissen. Daher teste mal ein wenig das Debuggen, schaue dir mal mal an, wie man sich überwachte Ausdrücke und deren Properties beim Debuggen anzeigt, manchmal sind auch Ausgaben auf der Console sinnvoll, usw. Ohne diese Tools ist eine effektive Fehlersuche nicht denkbar.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Antworten