Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Element aus einer TList (Generics.Collection) löschen
Hirschi - Fr 03.12.10 18:54
Titel: Element aus einer TList (Generics.Collection) löschen
Hallo Leute,
seit ein paar Stunden hänge ich an folgendem Problem:
Ich brauche einen eigenen Datentyp. Dafür wollte ich einen Record nehmen. Ungefähr so:
Delphi-Quelltext
1: 2: 3: 4:
| type TStep = record fromPos : Integer; toPos : Integer; end; |
Davon will ich beliebig viele in einer Liste verwalten. Dazu verwende ich eine Liste:
Die wird nun erstellt und ein paar Elemente hinzugefügt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| Steps := TList<TStep>.Create(); ... st.fromPos := Random(100); st.toPos := Random(100); Steps.Add(st); st.fromPos := Random(100); st.toPos := Random(100); Steps.Add(st); |
Das klappt auch alles ohne Fehler. Will ich aber nun ein beliebiges Element löschen, bekomme ich eine Zugriffsverletzung:
Delphi-Quelltext
1:
| Steps.Delete(Steps.Count-1); |
Wenn ich statt meinem Record einen primitven Datentyp (z.B. Integer) nehme, dann funktionierts es. Ich muss also irgendwas mit dem Record nicht verstanden haben. Hoffe, ihr habt einen Tipp.
MfG
Hirschi
Narses - Fr 03.12.10 19:04
Moin und :welcome: im Forum!
Du hast leider einen wichtigen Teil in deinem Code nicht gezeigt: die Speicherverwaltung. ;) Weiterhin wäre es auch nicht ganz unwichtig, wie die Fehlermeldung genau aussieht.
btw: Nimm lieber ein Objekt und die TObjectList, das ist besser als das Pointergehampel mit der TList... :? :nixweiss:
cu
Narses
bummi - Fr 03.12.10 21:00
@Narses
ich vermute alle Pointer zeigen auf die gleiche Variable
möglicherweise, sogar auf dem Stack...
Hirschi - Fr 03.12.10 21:02
Danke für die schnelle Antwort, Narses! :)
Narses hat folgendes geschrieben : |
Du hast leider einen wichtigen Teil in deinem Code nicht gezeigt: die Speicherverwaltung. ;) |
Na, da gibt es keine besondere. Deshalb nehm ich doch TList aus der Uni Generics.Collection und nicht eine normale TList.
Narses hat folgendes geschrieben : |
Weiterhin wäre es auch nicht ganz unwichtig, wie die Fehlermeldung genau aussieht.
|
Es ist schlicht eine Zugriffsverletzung auf eine Adresse im Speicher. Sie wird geworfen, wenn ich das Element löschen will. Insofern kann ich das nicht genauer schreiben, denn die Adresse ist ja jedesmal anders.
Narses hat folgendes geschrieben : |
btw: Nimm lieber ein Objekt und die TObjectList, das ist besser als das Pointergehampel mit der TList... :? :nixweiss: |
Richtig, das "Pointergehampel" wollte ich umgehen. ;)
MfG
Hirschi
jaenicke - Fr 03.12.10 21:15
Hirschi hat folgendes geschrieben : |
Deshalb nehm ich doch TList aus der Uni Generics.Collection und nicht eine normale TList. |
Das hat aber nichts damit zu tun, dass du auch neuen Speicher für jeden Record allozieren und evtl. am Ende wieder freigeben musst (ob die Freigabe bei der Collection automatisch passieren kann, weiß ich nicht). :nixweiss:
Hirschi hat folgendes geschrieben : |
Richtig, das "Pointergehampel" wollte ich umgehen. ;) |
Und warum machst du es dir dann unnötig schwer? Genau dafür gibt es wie schon geschrieben wurde Klassen und Objekte.
Hirschi - Mo 06.12.10 16:48
So wie ich es im Eingangsbeitrag beschrieben habe, funktioniert es auch bei einem Kollegen auf dem Rechner. Er verwendet allerdings Delphi 2010. Heißt, es muss wohl an meiner D2009-Installation liegen...sehr ärgerlich. Ich habe das nun mit Debug-DCUs durchlaufen und das Programm stützt in der DoDelete-Prozedur der Generics.Collection.pas bei der Zeile
FItems[Index] := Default(T);
ab. An der Prozedur ist von D2009 auf D2010 nichts passiert...tja, dann werd ich wohl was anderes (TObjectList) nehmen... Aber, theoretisch ginge mein Weg auch ;)
MfG
Hirschi
Narses - Mo 06.12.10 17:07
Moin!
Hirschi hat folgendes geschrieben : |
So wie ich es im Eingangsbeitrag beschrieben habe, funktioniert es auch bei einem Kollegen auf dem Rechner.
[...]
Aber, theoretisch ginge mein Weg auch |
Wenn du mit records arbeitest, dann wird das ganz sicher nicht korrekt funktionieren, denn für die Speicherverwaltung bei records ist
immer zusätzlicher Code nötig, das hat Delphi (und auch TP) noch nie selbst gemacht. :mahn: Insofern wundert mich, dass es irgendwo "laufen soll" (was man dann noch mal näher untersuchen sollte, heißt ja vielleicht auch nur: "stürzt nicht sofort ab" :mrgreen:)... :nixweiss:
cu
Narses
Hirschi - Mo 06.12.10 18:06
Narses hat folgendes geschrieben : |
Moin!
Wenn du mit records arbeitest, dann wird das ganz sicher nicht korrekt funktionieren, denn für die Speicherverwaltung bei records ist immer zusätzlicher Code nötig, das hat Delphi (und auch TP) noch nie selbst gemacht. :mahn: Insofern wundert mich, dass es irgendwo "laufen soll" (was man dann noch mal näher untersuchen sollte, heißt ja vielleicht auch nur: "stürzt nicht sofort ab" :mrgreen:)... :nixweiss:
|
Speicher beziehen und freigeben macht die TList<T> für dich, denn die Generics-Sachen haben eine eigene Speicherverwaltung.
Übrigens läuft es jetzt auch bei mir (endlich!), da ich eine Update der IDE gemacht habe. Auch bei einem anderen Kollgen mit D2009 läuft es genau wie beschrieben.
MfG
Hirschi
Narses - Mo 06.12.10 18:39
Moin!
Hirschi hat folgendes geschrieben : |
Speicher beziehen und freigeben macht die TList<T> für dich, denn die Generics-Sachen haben eine eigene Speicherverwaltung. |
Das glaube ich gerne, wenn es um Objekte geht. ;) Aber bei
records nicht. :idea: Ab D2k9 war doch FastMM mit dabei, da kann man doch eine Memory-Leak-Prüfung einschalten, das würde ich an deiner Stelle mal tun und sehen, ob da wirklich das passiert, was du erwartest... :?
cu
Narses
Kha - Mo 06.12.10 20:19
Ich kann zwar nicht selbst nachschauen, aber ich fürchte, ihr seht gerade Zeiger, wo keine sind ;) . Nach der Instanzierung der Generics dürfte ja ganz grob das (zumindest innerhalb des Compilers) dranstehen:
Delphi-Quelltext
1: 2: 3: 4: 5:
| type TList<TStep> = class ... var FItems : array of TStep; ... public procedure Add(aObj: TStep); |
Man kann natürlich auch eine
TList<TStep^> instanzieren (geh ich einfach mal von aus :) ), aber im obigen Fall sollten keine Zeiger beteiligt sein.
Narses - Mo 06.12.10 23:26
Moin!
OK, überzeugt. ;) (das mit dem internen dynamischen Array ist natürlich die Erklärung! :think:)
cu
Narses
Hirschi - Do 09.12.10 11:16
Danke für das arbeitsreiche Schlusswort, bummi ;) Und danke an alle Mitdiskutanten!
MfG
Hirschi
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!