Array lockere Bereichs- (Range-) check

Für Fragen rund um die Ide und zum Debugger
Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Array lockere Bereichs- (Range-) check

Beitrag von Erwin »

Hallo zusammen.

Code: Alles auswählen

 
var TestArray:Array[1..3] of Integer; // global
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  TestArray[5]:=25; // Wohl gemerkt: 5 existiert nicht!
  Button1.Caption:=IntToStr(TestArray[5]); // dito, ist aber dem Ganzem egal.
end;
 

Anstatt bei dem Fehler mit der Kompilierung an der entsprechenden Stelle stehen zu bleiben, gibt es nur ein Hinweis im Nachrichtenfenster. Insgesamt zieht er dies durch. Auf dem Button steht dann '25'.
Wenn man in dem Beispiel anstatt 5 dann 15 nimmt (TestArray[15]), gibt es beim Beenden des Programms eine komische teils nichtssagende Fehlermeldung.
Lazarus 2.2.0 / FP 3.2.4

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Array lockere Bereichs- (Range-) check

Beitrag von Socke »

Für eine strikte Prüfung mit Abbruch der Übersetzung gibt es die Range Checks:

Code: Alles auswählen

program Project1;
 
{$R+}
uses
    SysUtils;
 
var TestArray:Array[1..3] of Integer;
var s: String;
 
begin   
  TestArray[5]:=25;
  s:=IntToStr(TestArray[5]);
end.
Zuletzt geändert von Socke am Do 26. Jul 2018, 08:22, insgesamt 1-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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

Re: Array lockere Bereichs- (Range-) check

Beitrag von Mathias »

Anstelle von {$R+} kann man es auch in der IDE einstellen:
Project --> Projecteinstelllungen --> Debuggen --> Überprüfungen --> Bereich

. Insgesamt zieht er dies durch. Auf dem Button steht dann '25'.
Zufällig war der Speicherbereich frei, ansonsten hättest eine SIGSEV gehabt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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: Array lockere Bereichs- (Range-) check

Beitrag von af0815 »

Erwin hat geschrieben:Anstatt bei dem Fehler mit der Kompilierung an der entsprechenden Stelle stehen zu bleiben, gibt es nur ein Hinweis im Nachrichtenfenster.

Beim entwickeln solltest du mit Debug arbeiten, erst bei dem richtigen Release das deaktivieren.

Dafür gibt es ja auch die Buildmodes und die entsprecheden Einstellungen. Und - auch Hinweise gehören gelesen :-) und behoben. Zu diesen Thema hat es schon genügend Diskussionen gegeben. Deshalb kann man dieses Verhalten sehr fein beeinflussen, wenn man will. Wer es nicht macht muss halt fühlen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: Array lockere Bereichs- (Range-) check

Beitrag von Mathias »

Und - auch Hinweise gehören gelesen :-) und behoben. Zu diesen Thema hat es schon genügend Diskussionen gegeben. Deshalb kann man dieses Verhalten sehr fein beeinflussen, wenn man will. Wer es nicht macht muss halt fühlen.
Das ist so eine Sache. Manchmal bringt man eine Warnung kaum weg.

Bei der Matrix Warnt er, das sie nicht initialisiert ist.
Dabei steht am Anfang des Programmes ...Identity;
Identity macht nichts anderes als alle Werte in der Matrix initialisieren.

Code: Alles auswählen

var 
  WorldMatrix : TMatrix;    // Warning: Variable "WorldMatrix" read but nowhere assigned
begin
    WorldMatrix.Identity; // Wird als erstes ausgeführt.
 ....
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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: Array lockere Bereichs- (Range-) check

Beitrag von af0815 »

Aus der Sicht des Compilers ist es vollkommen richtig das WorldMatrix vor der ersten Verwendung nicht Initialisiert ist.
Du kannst dich hier entscheiden zB. die Meldung temporär zu unterdrücken {%H-} oder die WorldMatrix zu initialisieren.

Code: Alles auswählen

var 
  WorldMatrix : TMatrix;    // Warning: Variable "WorldMatrix" read but nowhere assigned
begin
     {%H-}WorldMatrix.Identity; // Wird als erstes ausgeführt.
 ....


Edit: Siehe auch http://wiki.freepascal.org/Turn_warning ... _on_or_off
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Array lockere Bereichs- (Range-) check

Beitrag von Erwin »

Danke.

Socke, den '/' mag er gar nicht. Er Jammert so lange, bis ich den lösche. Das mit dem R+ aber funktioniert.

Mathias, die Einstellung für den Bereich überpüfen klappte auch gut. Der Bereich war frei? Verwirrend. Verwirrend finde ich auch, dass so was wichtiges (und ich finde es wichtig) nicht von Anfang an aktiv ist, also Standardeinstellung ist.
Dort gibt es ja noch mehre Sachen zum Überprüfen?
I/O
Überlauf
Stack
Methodenaufrufe Prüfen
Code für Asserstions einfügen
Leider steht in meinen Lazaraus-Buch dazu nur, wie die Fehler dann heißen (202 etc.), aber um was es sich dabei genauer handelt, dazu schweigt es leider. Nach dem Motto: Keine Zeit es zu erklären, und der Leser (=Käufer) soll uns nicht länger damit nerven.
Während dafür anderswo unnötig viel über belangloses geschrieben wird.
Darf also selber woanders suchen, was es damit auf sich hat. Und dann grübeln, was genau dass im Zusammenhang mit Lazarus bewirkt? Zu mal manches eh keinen Sinn für mich ergibt. Ich meine Stack? Der kann doch überlaufen, glaube ich? Ist das nicht etwas, was generell nicht erlaubt sein sollte? Also Lazarus/FPC gar nicht erst zulassen sollte?
Und irre ich mich, aber sollte man in den Einstellungen dort doch am besten gleich alles prüfen lassen, oder?

af0815, darf ich aus Deiner Aussage entnehmen, dass standardmäßig der Debugger fast ausgeschaltet ist?
Lazarus 2.2.0 / FP 3.2.4

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Array lockere Bereichs- (Range-) check

Beitrag von kupferstecher »

Erwin hat geschrieben:Und irre ich mich, aber sollte man in den Einstellungen dort doch am besten gleich alles prüfen lassen, oder?

Die Überprüfungen sind teilweise recht Rechneintensiv. Z.B. beim Rangecheck, deinen Fehler hätte der Compiler bereits finden können, aber wenn der Arrayindex eine Variable ist, weiß der Compiler nicht, welchen Wert die Variable beim Ausführen annehmen wird. Um das abzusichern muss der Compiler bei jedem Arrayzugriff die Grenzen überprüfen. Er wird eine if-Abfrage einbauen in der Art "if (index < low(array)) or (index > high(array)) then throw exception...". Wenn du in einer Schleife 1000 mal auf ein Array zugreifst, müssen jedes Mal die Grenzen überprüft werden. Das ist jetzt sinngemäß zu verstehen, wie das im FPC gelöst ist, weiß ich nicht. Die Debuggerinformationen nützen wohl auch nur, wenn das Programm im Debugger läuft, d.h. aus der IDE gestartet wird.

Die Stacküberprüfung heißt - soviel ich weiß - dass das Programm regelmäßig schaut, ob der Stack noch in seinen zugewießenen Speicherbereich passt. Ist das nicht der Fall und gibt es keine Überprüfung, so wird er einfach über andere Speicherbereiche "drüberbügeln" oder das Betriebssystem antwortet mit einer Zugriffsverletzung. Die regelmäßigen Überprüfungen brauchen auch Rechenzeit und im produktiven Einsatz ist das Resultat oft das gleiche: Das Programm stürzt ab (Bzw. wird von der Überprüfungfunktion terminiert/abgeschossen).

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Array lockere Bereichs- (Range-) check

Beitrag von Socke »

Erwin hat geschrieben:Socke, den '/' mag er gar nicht. Er Jammert so lange, bis ich den lösche. Das mit dem R+ aber funktioniert.

Danke; ich habe den Tippfehler korrigiert.

Erwin hat geschrieben:Mathias, die Einstellung für den Bereich überpüfen klappte auch gut. Der Bereich war frei? Verwirrend. Verwirrend finde ich auch, dass so was wichtiges (und ich finde es wichtig) nicht von Anfang an aktiv ist, also Standardeinstellung ist.
Dort gibt es ja noch mehre Sachen zum Überprüfen?
I/O
Überlauf
Stack
Methodenaufrufe Prüfen
Code für Asserstions einfügen

Ob diese Standardeinstellungen sein sollten, ließe sich wohl am besten mit den Entwicklern auf der Lazarus-Mailingliste diskutieren. Hier lesen nur einige wenige mit.

Zu dem Punkt "Code für Assertions einfügen" finde ich beide Dokumentationen recht gut beschrieben: 1. https://www.freepascal.org/docs-html/prog/progsu5.html 2. https://www.freepascal.org/docs-html/rt ... ssert.html
An beiden Stellen steht leider nicht, warum man dieses Feature verwenden sollte: Mit Assertions dokumentiert man im Programmquelltext seine getroffenen Annahmen.
In einem Unit- oder Gesamttest bekommt man recht schnell eine Meldung, wenn die eigenen Annahmen nicht zutreffen. Dann kann man überprüfen, ob die eigenen Annahmen falsch sind oder an anderer Stelle ein Fehler vorliegt.
Während der Entwicklung braucht man vielleicht mehr Zeit, weil man seine Annahme explizit im Programm hinterlegen muss. Dafür gewinnt man in der Wartung und späterer Weiterentwicklung wichtige Hinweise, in welchem Rahmen eine Funktion ursprünglich gedacht war.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Array lockere Bereichs- (Range-) check

Beitrag von Erwin »

Socke hat geschrieben:Danke; ich habe den Tippfehler korrigiert.

Ach das war ein Tippfehler? Und ich dachte, es wäre vielleicht ein Art Befehl, der was auslösen soll?
Socke hat geschrieben:Ob diese Standardeinstellungen sein sollten, ließe sich wohl am besten mit den Entwicklern auf der Lazarus-Mailingliste diskutieren. Hier lesen nur einige wenige mit.

Oder man wird da eben besser informiert. Aber selbst mit Hilfe des Buchs zu Lazarus stehe ich eher verwirrt im Walde.

Bei Assertions geht es um Dokumentation des Quelltextes? Das allein hört sich schon für mich verwirrend an. Danke für die Vorwarnung.

kupferstecher hat geschrieben:Die Überprüfungen sind teilweise recht Rechneintensiv. Z.B. beim Rangecheck, deinen Fehler hätte der Compiler bereits finden können, aber wenn der Arrayindex eine Variable ist, weiß der Compiler nicht, welchen Wert die Variable beim Ausführen annehmen wird. Um das abzusichern muss der Compiler bei jedem Arrayzugriff die Grenzen überprüfen. Er wird eine if-Abfrage einbauen in der Art "if (index < low(array)) or (index > high(array)) then throw exception...". Wenn du in einer Schleife 1000 mal auf ein Array zugreifst, müssen jedes Mal die Grenzen überprüft werden. Das ist jetzt sinngemäß zu verstehen, wie das im FPC gelöst ist, weiß ich nicht. Die Debuggerinformationen nützen wohl auch nur, wenn das Programm im Debugger läuft, d.h. aus der IDE gestartet wird.

Ok, hätte ich mir teils auch denken können, dass man das deaktiviert hat wegen der Geschwindigkeit.
Normalerweise macht man sich bei den meisten Programmen keine Gedanken über die Vor-Einstellungen. Nur dann, wenn was nicht passt, was meist erst dann der Fall ist, wenn ich etwas anders als die Meisten es machen will.
Die setzen also auf Schnelligkeit, statt Gründlichkeit? Naja, je nach dem, ... kann das ein oder andere Angenehmer sein. Aber wäre schön, wenn man über diese Infos einfacher und schneller mit stolpern würde, also mitgeteilt bekäme. Weil dann weiß man auch, in dem Fall hier, dass man da ein wenig selbst kontrollieren muss. Also in dem man dann vor dem Finale überall (?) einen Hacken rein macht, und beim Final (wegen Programmgröße?) dann wieder raus nimmt. Stattdessen scheinen die Infos irgendwo versteckt zu sein?

kupferstecher hat geschrieben:Die Stacküberprüfung heißt - soviel ich weiß - dass das Programm regelmäßig schaut, ob der Stack noch in seinen zugewießenen Speicherbereich passt. Ist das nicht der Fall und gibt es keine Überprüfung, so wird er einfach über andere Speicherbereiche "drüberbügeln" oder das Betriebssystem antwortet mit einer Zugriffsverletzung. Die regelmäßigen Überprüfungen brauchen auch Rechenzeit und im produktiven Einsatz ist das Resultat oft das gleiche: Das Programm stürzt ab (Bzw. wird von der Überprüfungfunktion terminiert/abgeschossen).

Geht schon los ... . Nach dem was ich auf Wikipedia gelesen habe, muss es während der nutzung nicht zum Überlauf kommen, aber ein Angreifer kann dies verursachen. Auch sonst, wenn ich das richtig verstanden haben, kann im Falle eines Stack (Speicher?) überlauf wegen doppelter (?) Belegung von Platz (?) zu gravierenden Datenverlust bis hin zum Schaden an dem Programm selbst (?) kommen. Also ein ganz Gefährliche Sache?


Hm... vielleicht sollte ich extra Thread zu den Einstellungen aufmachen ... falls es den doch nicht schon gibt?
Lazarus 2.2.0 / FP 3.2.4

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

Re: Array lockere Bereichs- (Range-) check

Beitrag von Mathias »

Ok, hätte ich mir teils auch denken können, dass man das deaktiviert hat wegen der Geschwindigkeit.
Ich finde es gut, das es per Default deaktiviert ist. Wegen mir könnte man auch den Debugger deaktivieren. Da kommen sowieso im nur Fragen bei Anfängern, wieso die EXE so aufgebläht ist.
Wen jemand fortgeschritten ist, und weis wie das Debugging funktioniert, dann weis er auch wo man es einschaltet.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Array lockere Bereichs- (Range-) check

Beitrag von Warf »

Mathias hat geschrieben:Zufällig war der Speicherbereich frei, ansonsten hättest eine SIGSEV gehabt.


Zufällig ist es nicht ganz, er befindet sich ganz oben auf dem Stack (welcher nach oben wächst) was also bedeutet, wenn er nach oben über den array schreibt müsste er schon über alle Stackframes drüber schreiben bis es zu einer Zugriffsverletzung kommt, und der stack ist in produktiven programmen für gewöhnlich recht groß. Daher ist es recht unwahrscheinlich bei Stack-Arrays eine Zugriffsverletzung zu bekommen.

Erwin hat geschrieben:af0815, darf ich aus Deiner Aussage entnehmen, dass standardmäßig der Debugger fast ausgeschaltet ist?

Nein standardmäßig ist praktisch die minimale funktionalität gegeben um den GDB zu verwenden. Für kleinere sachen ausreichend, für größere Projekte würde ich einfach die Default Build-Modes Debug und Release verwenden.

kupferstecher hat geschrieben:Die Stacküberprüfung heißt - soviel ich weiß - dass das Programm regelmäßig schaut, ob der Stack noch in seinen zugewießenen Speicherbereich passt. Ist das nicht der Fall und gibt es keine Überprüfung, so wird er einfach über andere Speicherbereiche "drüberbügeln" oder das Betriebssystem antwortet mit einer Zugriffsverletzung. Die regelmäßigen Überprüfungen brauchen auch Rechenzeit und im produktiven Einsatz ist das Resultat oft das gleiche: Das Programm stürzt ab (Bzw. wird von der Überprüfungfunktion terminiert/abgeschossen).


Bist du dir da sicher? denn die Stack Limits werden afaik vom Betriebsystem enforced (z.b. unter linux in der limits Datei), zwar muss das OS kein limit haben (z.b. linux: ulimit -s unlimited), aber normalerweise ist ein Limit eingestellt. Daher wäre diese Option in den Meißten fällen nutzlos, und damit nur Laufzeitverschwendung. Ich hab da aber keine ahnung was diese Option macht.

Erwin hat geschrieben:Bei Assertions geht es um Dokumentation des Quelltextes? Das allein hört sich schon für mich verwirrend an. Danke für die Vorwarnung.


Assertions sind debug code die ein Verboses Failen verursachen. z.B. assert(x1>x2 , 'X1 needs to be bigger than x2'). Wenn die Assertion failed, dann crasht dein programm mit der Message die angegeben wurde (Denn ein Crash + Message ist normalerweise immer besser als wenn der PC still den fehler schluckt und einfach weitermacht mit eventuell falschen daten). Im release code deaktivierst du dann assertions, damit werden diese nicht ausgeführt um Leistung zu sparen, und Verbose Fehlermeldungen zu unterdrücken (mit denen der Endnutzer meist nichts anfangen kann). Immer wenn du irgendwelche annahmen machst (z.B. das argument muss >= 0 sein oder so) solltest du diese als assertions einbauen. Das führt dazu das wenn du irgendwann dein programm änderst, du nicht vergisst das diese annahmen (so genannte invarianten) noch gelten. Wenn du stattdessen dir denkst, "ich ruf das eh immer >= 0 auf, also brauch ich keine abfgrage" kracht es spätestens wenn du nach 6 monaten mal ein update machst, und das schonwieder komplett vergessen hast.
Assertions sind aber aussschließlich zum Debuggen für entwickler gedacht, und sollten im produktiven Code nicht drin sein

Erwin hat geschrieben:Ok, hätte ich mir teils auch denken können, dass man das deaktiviert hat wegen der Geschwindigkeit.
Normalerweise macht man sich bei den meisten Programmen keine Gedanken über die Vor-Einstellungen. Nur dann, wenn was nicht passt, was meist erst dann der Fall ist, wenn ich etwas anders als die Meisten es machen will.
Die setzen also auf Schnelligkeit, statt Gründlichkeit? Naja, je nach dem, ... kann das ein oder andere Angenehmer sein. Aber wäre schön, wenn man über diese Infos einfacher und schneller mit stolpern würde, also mitgeteilt bekäme. Weil dann weiß man auch, in dem Fall hier, dass man da ein wenig selbst kontrollieren muss. Also in dem man dann vor dem Finale überall (?) einen Hacken rein macht, und beim Final (wegen Programmgröße?) dann wieder raus nimmt. Stattdessen scheinen die Infos irgendwo versteckt zu sein?

Lazarus kann dir den Standard Release und Debug Modus per klick erstellen, die haben ziemlich gute voreinstellungen: Projekteinstellungen->Compilereinstellungen, oben Erstellmodi haken setzten, auf den ... button clicken und dann auf Debug Und Release Modus erstellen klicken. Den Default modus kannst du dann löschen.
Über die Dropdown box kannst du dann den aktiven modus wählen

Erwin hat geschrieben:Geht schon los ... . Nach dem was ich auf Wikipedia gelesen habe, muss es während der nutzung nicht zum Überlauf kommen, aber ein Angreifer kann dies verursachen. Auch sonst, wenn ich das richtig verstanden haben, kann im Falle eines Stack (Speicher?) überlauf wegen doppelter (?) Belegung von Platz (?) zu gravierenden Datenverlust bis hin zum Schaden an dem Programm selbst (?) kommen. Also ein ganz Gefährliche Sache?


Wie gesagt in den meißten fällen wird dir das Betriebsystem nicht genug speicher zur Verfügung stellen damit du überhaupt eine so genannte heap collision (stack der nach oben wächst und heap der nach unten wächst überschneiden sich) bekommen kannst. Man muss schon aktiv, mit administratorrechten das bei seinem Betriebsystem einstellen damit man da was kaputt machen kann.

Das hauptproblem für eine Stacküberlauf sind aber auch keine angreifer, sondern dumme programmierer. z.B funktionen mit großem stack:

Code: Alles auswählen

procedure SomeRecursiveProcWithVeryLargeStack(i: Cardinal);
var arr: array[0..1000000] of Byte; // 1MB stack size
begin
 if LongBool(i) then SomeRecursiveProcWithVeryLargeStack(i-1);
end;

Ein entsprechend großes i würde dir damit eine heap collisiob geben. Aber, mit dynamischen arrays oder pointer auf statische arrays und new-dispose, wäre das ganze kein problem

Hm... vielleicht sollte ich extra Thread zu den Einstellungen aufmachen ... falls es den doch nicht schon gibt?

Es bräuchte einfach eine vernünftige Wikiseite die alles wenigstens kurz erklärt (und vor allem alles auf einer Seite)

Mathias hat geschrieben:Ich finde es gut, das es per Default deaktiviert ist. Wegen mir könnte man auch den Debugger deaktivieren. Da kommen sowieso im nur Fragen bei Anfängern, wieso die EXE so aufgebläht ist.
Wen jemand fortgeschritten ist, und weis wie das Debugging funktioniert, dann weis er auch wo man es einschaltet.


Das ding ist das es generell zum debugging nicht sonderlich viele informationen gibt. Am anfang hab ich 90% der zeit mit WriteLn und ShowMessage gedebuggt, weil ich das Variablen überprüfen feature nicht kannte.

Zum debuggen generell,
Für etwas verbosere ausgaben und praktisch alle memory checks die man sich vorstellen kann, kann man unter Linux auch Valgrind verwenden. Das ganze hat nen heftigen overhead (faktor 100 langsamer mindestens), bietet dir aber eine vielzahl an tools um sehr wiederliche fehler zu finden. Das übernimmt praktisch die aufgabe von Heaptrc, rangechecks und vielem mehr. Aber meißt sollten die FPC features und der GDB bereits schon reichen und schneller sein.

Valgrind erstellt ein sog. shadow memory modell, was praktisch für jede Memory location zusätzliche informationen bereitstellt, um somit extrem akkurate tests durchzuführen.

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

Re: Array lockere Bereichs- (Range-) check

Beitrag von Mathias »

Am anfang hab ich 90% der zeit mit WriteLn und ShowMessage gedebuggt, weil ich das Variablen überprüfen feature nicht kannte.
Ich mache es meisten immer noch so, da es der einfachte und schnellste Weg ist.
Unter Linux kann man sehr einfach eine einfache Konsole auf tun. "Ansicht --> Debuggerfenster --> Terminal-Ausgabe"
Dort kann man gut rasch was mit Writeln(); reinschreiben. Wen der Fehler gefunden ist, einfach das Writeln wieder löschen.
Das Debugger-Fenster kann man immer offen lassen, das es keinen Einfluss auf den kompilierten Code hat.

Das gute dabei, die EXE wird dabei nicht verändert, wie bei den Debuggereinstellungen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Array lockere Bereichs- (Range-) check

Beitrag von Socke »

Mathias hat geschrieben:Dort kann man gut rasch was mit Writeln(); reinschreiben. Wen der Fehler gefunden ist, einfach das Writeln wieder löschen.
Das Debugger-Fenster kann man immer offen lassen, das es keinen Einfluss auf den kompilierten Code hat.

Wenn du die Unit LazLogger verwendest und von WriteLn() auf DebugLn() umstellst, musst du deinen Code nicht ändern. Du kannst das ganze sogar produktiv verwendet und deine Anwender erstellen im Hintergrund eine Logdatei, die du einfach auswerten kannst.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Array lockere Bereichs- (Range-) check

Beitrag von Warf »

Mathias hat geschrieben:Ich mache es meisten immer noch so, da es der einfachte und schnellste Weg ist.
Unter Linux kann man sehr einfach eine einfache Konsole auf tun. "Ansicht --> Debuggerfenster --> Terminal-Ausgabe"
Dort kann man gut rasch was mit Writeln(); reinschreiben. Wen der Fehler gefunden ist, einfach das Writeln wieder löschen.
Das Debugger-Fenster kann man immer offen lassen, das es keinen Einfluss auf den kompilierten Code hat.

Das gute dabei, die EXE wird dabei nicht verändert, wie bei den Debuggereinstellungen.


Ich verwende WriteLn sobald ich verschiedene threads laufen hab die parallel irgendwas machen (da ich durch das breaken von einem thread ja die raceconditions selbst wieder ändern würde). Das problem dabei ist, unter Windows müssen Formularanwendungen STDIn und STDOUT schließen, sonst popt immer das CommandLine fenster mit start der Anwendung auf (FPC macht das automatisch mit dem AppType compilerswitch), daher würde man beim WriteLn dann eine Runtime Exception bekommen.

Was ich dafür mache sind normalerweise Definitionen Debug und Release zu den erstellmodi hinzufügen und dann etwa so:
Im LPR/program file:

Code: Alles auswählen

{$ifdef Debug}
  {$AppType Console}
{$else}
  {$AppType GUI}
{$endif}

Plus eine eigene Unit (pseudocode, keine lust die echte unit jetzt rauszusuchen):

Code: Alles auswählen

unit Logger;
{$Mode ObjFPC}{$H+}
uses Sysutils;
 
...
implementation
var LogFile: Text;
 
procedure LogLine(ln: String);
begin
  WriteLn(LogFile, '[%s]%s'.Format([DateToStr(Now), ln]));
end;
 
initialization
  {$ifdef Debug}
    LogFile := Output;
  {$else}
    AssignFile(LogFile, LogPath);
    Append(LogFile);
  {$endif}
  WriteLn(LogFile, '/-- ', DateToStr(Now), ' --\ ');
finalization
  WriteLn(LogFile, '\-- ',  DateToStr(Now) , ' --/');
  {$ifndef Debug}
    CloseFile(LogFile);
  {$else}
end.

Antworten