Ist das FreePascal BUG?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

Ist das FreePascal BUG?

Beitragvon Soner » 5. Aug 2017, 01:38 Ist das FreePascal BUG?

Kann es sein dass hier Free Pascal ein Fehler macht oder ich? Das ganze wird in Delphimodus kompiliert.
Ich erkläre es am besten mit Quelltext liest bitte Kommentare.
Die Variable i ist integer, Item.FChildren.Count ist auch integer und es ist manchmal 1 und manchmal 0.
Code: Alles auswählen
 
 for i := 0 to (Item.FChildren.Count - 1) do begin
     // dieser block wird 2 mal ausgeführt  wenn Item.FChildren.Count=1 ist
     // und erzeugt natürlich Index Fehler, weil i ist 1 und
 end;
 


Dann habe ich es variert zu:
Code: Alles auswählen
 
 k:= (Item.FChildren.Count - 1);
 for i := 0 todo begin
     // dieser Block wird auch zwei mal ausgeführt  bei count=1
     // wie bei Variation 1
 end;
 


Dann habe ich es zu While-Schleife geändert und da läuft es richtig:
Code: Alles auswählen
 
 i:= 0;
 while i<Item.FChildren.Count do
     // Jetzt läuft es richtig, d.h.  bei
     // Item.FChildren.Count =1 wird es nur einmal ausgeführt
    Inc(i);
 end;
 


Ich habe dann in einem Neuen Beispielprogramm ähnliches gemacht, da lief es ohne Probleme, auch in Delphimodus:
Code: Alles auswählen
 
procedure TForm1.FormCreate(Sender: TObject);
var i, k: integer;
begin
  k:=(1-1);
  for i:=0 to k do
    Caption:=i.ToString;
end;
 
Soner
 
Beiträge: 371
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Mathias » 5. Aug 2017, 07:55 Re: Ist das FreePascal BUG?

Was ist Item, eine Deklaration wäre hilfreich.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3249
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Soner » 5. Aug 2017, 09:32 Re: Ist das FreePascal BUG?

Item ist TElTreeItem = class(TPersistent).
Ich lade das ganze mal hoch, es ist sowieso Freeware sofern man kein Abkömmling erstellt. Es ist Eltree-lite, ich habe im Schnelldurchgang zu Lazarus convertiert. Es läuft aber zeichnet keine "tree-items", ich muss noch Zeichen routinen überarbeiten.
Nun zurück zum Problem, es geht allgemein um dieses Verhalten, das habe ich bei Freepascal schon einige male mit Listen erlebt.
Diese Schleife befindet sich in ElTree.pas (procedure TElTreeItems.Iterate;).
Wenn ihr Beispielprogramm ladet und es laufen läßt, stoppt der Debugger ein paarmal dort, aber diese Zählen nicht. Erst wenn es erst in Eltreeesimplelaz1form.pas bei der Zeile:
Code: Alles auswählen
    aLand:=ElTree1.Items.AddItem(nil);

stoppt, dann achten, weil es dann anschließend bei
Code: Alles auswählen
procedure TElTreeItems.Iterate;

stoppt und dann ist das Fehlverhalten zu beobachten.

Originale Prozedure ist das hier:
Code: Alles auswählen
 
  procedure IntIterate(VisibleOnly: boolean; Item: TElTreeItem);
  var
    i: integer;
  begin
    inc(j);
    if (j >= 0) and ((not VisibleOnly) or ((not Item.Hidden) or (not FOwner.FilteredVisibility))) then IterateProc(Item, j, DoContinue, IterateData, FOwner);
    if not (DoContinue) then exit;
    if (not (VisibleOnly)) or (Item.Expanded) then
      for i := 0 to Item.FChildren.Count - 1 do
      begin
        if (not VisibleOnly) or ((not TElTreeItem(Item.FChildren[i]).Hidden) or (not FOwner.FilteredVisibility)) then
          IntIterate(VisibleOnly, TElTreeItem(Item.FChildren[i]));
        if not (DoContinue) then exit;
      end;
  end;
 
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Soner
 
Beiträge: 371
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon mschnell » 5. Aug 2017, 09:50 Re: Ist das FreePascal BUG?

Soner hat geschrieben:1:
for i := 0 to (Item.FChildren.Count - 1) do begin
...
2:
k:= (Item.FChildren.Count - 1);
for i := 0 to k do begin
...
3:
i:= 0;
while i<Item.FChildren.Count do
...

1: Item.FChildren.Count wird nur einmal vor der Schleife ausgewertet (anders als bei einem "for"-statement in C ).
2: ebenso, hier aber offensichtlich (wäre auch in C so) )
3: Item.FChildren.Count wird bei jedem Schleifendurchgang ausgewertet.

Wenn item in der Scheife verändert wird, kann es zu besagtem Index-Fehler / Zugriffsverletzung kommen.

-Michael
mschnell
 
Beiträge: 3159
Registriert: 11. Sep 2006, 09:24
Wohnort: Krefeld
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ) | 
CPU-Target: X32 / X64 / ARMv5
Nach oben

Beitragvon Soner » 5. Aug 2017, 10:22 Re: Ist das FreePascal BUG?

mschnell hat geschrieben:...
1: Item.FChildren.Count wird nur einmal vor der Schleife ausgewertet (anders als bei einem "for"-statement in C ).
2: ebenso, hier aber offensichtlich (wäre auch in C so) )
..
-Michael

So sollte es sein, aber das macht es nicht. Ich prüfe sowohl vor Schleifeneintritt auch auch in der Schleife auf Item.FChildren.Count, obwohl es 1ist, läuft die Schleife zweimal.
Code: Alles auswählen
 
      i:=Item.FChildren.Count; // = 1
      for i := 0 to (Item.FChildren.Count - 1) do
            begin
              k:=Item.FChildren.Count; // = 1, auch beim 2. Schleifenlauf
              if (not VisibleOnly) or ((not TElTreeItem(Item.FChildren[i]).Hidden) or (not FOwner.FilteredVisibility)) then
                IntIterate(VisibleOnly, TElTreeItem(Item.FChildren[i]));
              if not (DoContinue) then exit;
            end;   
 
Soner
 
Beiträge: 371
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Soner » 5. Aug 2017, 10:38 Re: Ist das FreePascal BUG?

Ich habe es ganz oben geschrieben aber mache mal deutlich, ist das nicht falsches Laufverhalten?
Code: Alles auswählen
 
      b:=(Item.FChildren.Count - 1);
     // obwohl b=0 ist wird die schleife fortgesetzt und i wird 1.
      for i := 0 to b do
            begin
              k:=Item.FChildren.Count;
              if (not VisibleOnly) or ((not TElTreeItem(Item.FChildren[i]).Hidden) or (not FOwner.FilteredVisibility)) then
                IntIterate(VisibleOnly, TElTreeItem(Item.FChildren[i])); //hier wird die Prozedur nochmal aufgerufen, Rekursion.
              if not (DoContinue) then exit;
             //hier musste die Schleife Verlassen werde, weil b=0 ist, aber geht weiter zum Schleifenanfang.
            end;
    end;   
 


Ich glaube ich habe den Fehler gefunden. Weil das eine Rekursion ist, kompiliert der freepascal den Kode falsch, anders ist es nicht zu erklären.
Soner
 
Beiträge: 371
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Soner » 5. Aug 2017, 11:14 Re: Ist das FreePascal BUG?

Ich habe weiter mit Debugger untersucht:
Code: Alles auswählen
 
 
  procedure IntIterate(VisibleOnly: boolean; Item: TElTreeItem);
  var
    i: integer;
  begin
    inc(j);
    if (j >= 0) and ((not VisibleOnly) or ((not Item.Hidden) or (not FOwner.FilteredVisibility))) then
        IterateProc(Item, j, DoContinue, IterateData, FOwner); //<--- hier gibt es auch falsches Verhalten
        //Vor dem Eintritt in IterateProc ist:    item<>nil und DoContinue=true, j=0
        //in die IterateProc-FUnktion kommt an, immer : Item=nil
       // DoContinue= irgend ein integer zahl,
        //j= irgend ein integer zahl,
 
 
    if not (DoContinue) then exit;
    if (not (VisibleOnly)) or (Item.Expanded) then
      for i := 0 to Item.FChildren.Count - 1 do
      begin
        if (not VisibleOnly) or ((not TElTreeItem(Item.FChildren[i]).Hidden) or (not FOwner.FilteredVisibility)) then
          IntIterate(VisibleOnly, TElTreeItem(Item.FChildren[i]));
        if not (DoContinue) then exit;
      end;
  end;
 


Wenn ich mich nicht irre, muß es ein Freepascal-Fehler geben.
.
Soner
 
Beiträge: 371
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon wp_xyz » 5. Aug 2017, 11:24 Re: Ist das FreePascal BUG?

Um die FPC-Leute davon zu überzeugen, dass hier wirklich ein Compiler-Fehler vorliegt, musst du ein einfaches Test-Projekt erstellen, das den Fehler zeigt. Eine Fremdkomponente mit 20 Dateien wird sich niemand ansehen.
wp_xyz
 
Beiträge: 2272
Registriert: 8. Apr 2011, 08:01

Beitragvon Timm Thaler » 5. Aug 2017, 14:23 Re: Ist das FreePascal BUG?

Soner hat geschrieben:Ich glaube ich habe den Fehler gefunden. Weil das eine Rekursion ist, kompiliert der freepascal den Kode falsch, anders ist es nicht zu erklären.


Nanana, vielleicht solltest Du den Fehler mal bei Dir suchen. for ... do ist ja nun keine neue Erfindung, meinst Du nicht, es wäre auch anderen schon aufgefallen, wenn das falsch kompiliert würde.

Leider gibst Du nur unvollständige Angaben, daher ist das nur Vermutung:

for führt nicht die Schleife zweimal aus, sondern for führt die Schleife einmal aus, so wie das sein soll, geht dann in die Rekursion und führt die Schleife nochmal aus. Jedesmal ist i = 0 und nach der Schleife 1.

Den Abbruch nach dem zweiten Ausführen macht dann DoContinue, wobei unklar ist, wo das mit welchen Werten gefüttert wird.
Timm Thaler
 
Beiträge: 439
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

• Themenende •

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: Google [Bot] und 4 Gäste

porpoises-institution
accuracy-worried