Entwickler-Ecke

Sonstiges (Delphi) - ACCESS Violation bei TStrings.Free


mtm - Mo 20.03.17 17:19
Titel: ACCESS Violation bei TStrings.Free
Hallo zusammen,
ich hätte da mal ein Problem. Ich bastele mir gerade eine Chorverwaltung. Funktioniert soweit auch, bis auf ein kleines Problem.
Ich möchte ein Formular öffnen, in dem die Aufführungen und die dort aufgeführten Werke verwaltet werden können. Dabei möchte ich alle vorhandenen Werke in eine ComboList laden.
Das passiert in folgendem Codeschnipsel :

Delphi-Quelltext
1:
2:
3:
4:
    sl := TStringList.Create;
    aktChor.LoadPieces(sl);  // lade alle Stücke, die für den aktuellen Chor vorhanden sind.
    cboPiece.Items.Assign(sl);  // diese Stücke in die Combobox füllen
    sl.Free;


In der procedure LoadPieces der Klasse aktChor passiert nun folgendes :

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TChor.LoadPieces(var sl: TStrings);
var
  i,a,s: Integer;
  cs: TCSKlasse;
  st: TStueck;
  txt: String;
begin
  sl.Clear;  // evtl vorhandenen Inhalt löschen
  for i := 0 to CSLst.Count - 1 do begin  // in CSLst sind alle für diesen Chor voehandenen Stücke aufgelistet,
    cs := TCSKlasse(CSLst.Objects[i]);  // Object ist der PrimaryKey des Stückes
    if cs.Chor = fIdx then begin  // fidx = PrimaryKey des aktuellen Chores
      s := cs.Stueck;  
      a := SLst.IndexOf(IntToStr(cs.Stueck));  // ist das Stück vorhanden in SLst (Liste aller Stücke)
      if a > -1 then begin   // jawoll, ist vorhanden
        st := TStueck(SLst.Objects[a]);  // einzelnes Stück laden
        txt := st.Titel + ' (' + st.Komponist+')';
        sl.AddObject(txt,TObject(s));
      end;
    end;
  end;
end;


Dieser Teil funktioniert soweit auch ganz gut. Im Debugger ist die StringListe sl so gefüllt, wie ich mir das gedacht habe. Wenn ich den oberen CodeTeil schrittweise durchgehe funktioniert eigentlich alles wunderbar auch der Assign auf die Combobox wird ohne Murren ausgeführt.
Bei
Zitat:
sl.Free
tritt jedoch ein ACCESS VILOATION auf.

Fehler1

Da es wohl keinen Sinn ergibt, das komplette Projekt zu posten, hoffe ich, daß irgendjemand von Euch eine Idee hat, woran das liegen könnte.

Danke im Voraus
mtm

Edit : Ich bin scheinbar ein wenig blind. Der Aufruf des oberen Code-Schnipsels erfolgte zu früh.


Slipstream - Mo 20.03.17 19:17

Wieso sl.free ein exception wirft, weiss ich nicht. Aber ich sehe, dass du sl als Var-Parameter übergibst. Das ist falsch. TStrings wird nie als Var-Parameter übergeben, denn damit übergibst du lediglich den Pointer auf den Beginn der List. Der soll aber nicht verändert werden dürfen. Übergebe den sl als const.


haentschman - Di 21.03.17 08:29

Moin... :P
Ich hätte da mal ein paar Tips. :wink:

1. Da dein Delphi Generics hat kannst du sie auch nutzen. :zwinker:
Ich gehe davon aus das CSLst die TObjectList ist... Da könnte man auch TObjectList<TCSKlasse> draus machen. Erstens kann man sich den cast sparen und die Objekte sind vom Debugger einsehbar. :zustimm:
2. Die Stücke kannst du auch in der Klasse verwalten statt TStringList...TObjectList<TStueck>;
2. Bitte verwende keine Abkürzungen sondern sprechende Namen für die Variablen. Im Moment ist des gut weil du daran arbeitest. In 2 Monaten hast dann schon Schwierigkeiten cs aufzulösen. :zwinker:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
CSLst: TObjectList<TCSKlasse>;
...
procedure TChor.LoadPieces(var sl: TStrings);
var
  i,a,s: Integer;
  cs: TCSKlasse;
  st: TStueck;
begin
  sl.Clear;  // evtl vorhandenen Inhalt löschen
  for i := 0 to CSLst.Count - 1 do begin  // in CSLst sind alle für diesen Chor voehandenen Stücke aufgelistet,
    cs := CSLst[i];  // Object ist der PrimaryKey des Stückes
    if cs.Chor = fIdx then begin  // fidx = PrimaryKey des aktuellen Chores
      s := cs.Stueck;  
      a := SLst.IndexOf(IntToStr(cs.Stueck));  // ist das Stück vorhanden in SLst (Liste aller Stücke) !! statt in der Stringliste in der Objektliste suchen. 
      if a > -1 then begin   // jawoll, ist vorhanden
        st := SLst[a];  // einzelnes Stück laden
        sl.AddObject(st.Titel + ' (' + st.Komponist+')', s);
      end;
    end;
  end;
end;


...nur so als Anregung. :zwinker: