Moin!
Zitat von
Jan:
Kann mir denn dabei wirklich keiner Helfen?
Müsste doch für die vielen erfahrenen Programmierer hier kein Problem sein, oder?
Nun mach mal kein Stress, es gibt Leute die arbeiten auch mal mehr als nur die üblichen 8 Stunden, daher kann es auch mal ein wenig dauern - und pushen innerhalb von 24 Stunden ist eh nicht gerne gesehen.
Zitat von
Jan:
Also soweit verstehe ich was du sagen willst, durch das freeandnil wird nicht das objekt gelöscht, auf das die variable zeigt, sondern die im Speicher abgelegt Adresse zu meinem Objekt, so dass meine Variable nichtmehr auf mein Objekt zeigt.
Ähm, also FreeAndNil() macht das so wie der Name schon sagt: er gibt erst das Objekt frei was an der Stelle steht wo die Instanzenvariable hinzeigt. Nun hat die Variable aber die Adresse noch wie zuvor, nur ein Zugriff auf diese führt zum Absturz, weil dort wo sie hinzeigt existiert kein Objekt mehr. Und damit das nicht passiert setzt die FreeAndNil() Funktion die Variable noch auf Nil, weil 0 ist eine ungültige Adresse und daher kann man nachprüfen ob das Objekt existiert - zumindest ob eine Adresse angegeben ist. Ich hatte mich bei FreeAndNil() nur auf den Nil Teil der Funktion bezogen - vorher gibt sie auch ordentlich das Objekt noch frei - das hatte ich oben in dem Zusammenhang weggelassen.
Zitat von
Jan:
Delphi-Quellcode:
a) temp:=tstringlist(listview1.selected.data);
b) freeandnil(temp);
c) showmessage(workarray[0].strings[0]);
Soweit ich noch weiss, ist hier WorkArray[0] die gleiche StringList wie in ListView1.Selected.Data, richtig? Damit sind wir wieder bei dem oben genannten Problem:
Du hast in dem Code 4 Stellen im Speicher:
1. Stelle: Das ist ein grösserer Block der die Instanz von der TStringList enthält
2. Stelle: Das ist die Data Eigenschaft eines TListItems der TListView (also die Data Eigenschaft eines Elements der TListView). Diese Stelle im Speicher enthält nicht das Objekt sondern nur die Adresse wo
1. liegt (ein Pointer)
3. Stelle: Das ist ein Eintrag in dem Array WorkArray[] welches einfach auch nur die Adresse des Objektes (welches hier
1. ist) enthält. Also auch hier nur ein Zeiger auf die
1. Stelle - kein Objekt selber.
4. Stelle: der Platz im Speicher für die Variable Temp. Auch ein Zeiger - ein Zeiger der auf nix zeigt.
So und nun nochmal dazu, was dein Code macht:
Zeile a): Der Inhalt des Zeigers aus
2. (also nur die Adresse wo
1. im Speicher liegt) wird kopiert und in 4. abgelegt. 4. ist auch nur ein Zeiger und zeigt danach auf die selbe Stelle im Speicher wie
2.
Zeile b): Das Objekt was an
Stelle 1 liegt wird freigegeben - der Speicher bei der
1. Stelle wird also freigegeben und wird vom Programm für anderes genutzt. Danach wird durch FreeAndNil() in Stelle 4 noch eine 0 eingetragen, so dass Stelle 4 nicht mehr weiss wo der Speicherblock aus
1. geblieben ist.
Stelle 2 und
Stelle 3 aber hat keiner was gesagt, daher zeigen diese immernoch auf die gleiche Stelle im Speicher - da wo
1. mal lag, aber nun ja nicht mehr.
Zeile c): Du greifst auf die
3. Stelle im Speicher zu, welche ja immernoch wie die
2. Stelle im Speicher noch die alte Position von
1. beinhalteten. Dort greift nun auch ShowMessage zu um sich von dort den String zu holen (aus dem Speicherbereich bei
1.), aber da ist ja nix mehr, daher greift er ins Leere und es gibt eine
AV.
So langsam weiss ich nicht mehr wie ich das technisch erklären soll. Falls es immernoch hapert, dann hier nochmal eine "nicht-technische Erklärung":
Folgende Situation:
Du hast ein Geheimversteck mit 2 Freunden. Dieses kennt ihr alle 3 und jeder kann da mal was hinpacken und die anderen können es sich dann anschauen. Daher folgende Situation:
Wir haben ein Versteck V und 2 Freunde (Freund1, Freund2) und natürlich dich (Jan).
Situation am Anfang:
Freund1 kennt V
Freund2 kennt V
Jan kennt V
Sagen wir mal du musstest letztens feststellen das jemand anders das Versteck gefunden hatte und somit ist es nicht mehr sicher, geschweige denn geheim. Nun nimmst du die dort von euch abgelegte Dinge erstmal in Verwahrung und suchst ein neues Versteck. Als du eins gefunden hast, musst du ja nun noch deinen beiden Freunden bescheid geben wo sich dies neue Versteck befinden - du selber weisst es ja, du hast es ja gefunden. Nun ist aber das Problem, das dein Handy alle ist und du somit Freund1 und Freund2 nicht über das neue Geheimversteck (nennen wir es mal N) informieren kannst. Daher haben wir danach folgende Situation:
Freund1: kennt nur V - also das alte Versteck (welches nicht mehr existiert)
Freund2: kennt auch nur V - also auch nur das alte Versteck (welches nicht mehr existiert)
Jan: du kennst das neue Versteck N
Problem: Wenn du das nächste mal einen von beiden triffst und ihnen nicht erzählst wo das neue Versteck N sich befindet und du ihnen z.B: nur sagst das du die Lösungen für die neue Mathearbeit im Geheimversteck hinterlegt hast, dann schauen Freund1 und Freund2 beim alten Versteck V nach, aber da ist nix mehr - daher schreiben sie nächsten Tag eine schlechte Arbeit und sind böse auf dich (->
Exception ).
Ende...
Grundlegend: jeder (du und deine Freunde) können sich für sich selber die Position des Versteckes merken. Wenn du ihnen die neue Position nicht mitteilst, haben sie immernoch die alte Position im Kopf. Gleiches gilt für die Variablen die sich die Position des Objektes merken (Temp, WorkArray[0], ListView1.Selected.Data): wenn du nicht allen Bescheid sagst, wissen manche nix von der Veränderung - sie merken sich das auch alle für sich.
Ich hoffe das dies hilft den Groschen weiter rutschen zu lassen...
MfG
Muetze1
PS: Die Story hat (c) - ich rede gerade mit einem Verleger über ein Zeiger-Kinderbuch... *g*