AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

untypisierter pointer

Ein Thema von Jan · begonnen am 4. Dez 2004 · letzter Beitrag vom 21. Jan 2005
Antwort Antwort
Seite 3 von 3     123   
Muetze1
(Gast)

n/a Beiträge
 
#21

Re: untypisierter pointer

  Alt 13. Dez 2004, 19:46
Moin!

Ich verstehe nicht wie du auf die Idee kommst, das WorkArray[0] Nil werden sollte? FreeAndNil() setzt die Variable Temp auf Nil, aber Temp ist doch eine andere Variable und Speicherplatz als WorkArae[0]. Und WorkArea[0] enthält immernoch die alte Adresse genauso wie listview1.selected.data -- diese beiden Stellen hast du auch nie auf Nil gesetzt und daher enthalten die auch noch die alten Adressen und daher kommt es auch beim Zugriff zu einer AV an einer Adresse die nicht gerade neben 000000h liegt...

Also: wie kommst du auf die Idee, das WorkArea[0] Nil sein sollte??

MfG
Muetze1
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#22

Re: untypisierter pointer

  Alt 20. Jan 2005, 11:05
Hallo Muetze1,
sorry, dass ich so spät antworte, aber die meldungen von DP auf Antworten landen immer im Spamverdacht, warum auch immer...
Also zu deinen Fragen:
In delphi sind doch meines Wissens nach Variabeln auch nichts anderes als Zeiger auf einen Speicherinhalt. Und ist es nicht auch so, dass wenn ich zwei Objekte a und b habe, dass dann
Delphi-Quellcode:
a:=b;
a:=nil;
auch b nil setzt? weil doch bei a:=b lediglich eine Referenz auf b an a übergibt, oder irre ich da?

Und nach dem Prinzip dachte ich würde auch das funktionieren:

Delphi-Quellcode:
temp:=tstringlist(listview1.selected.data);
      freeandnil(temp);
Data ist ein Zeiger, und jetzt wird die Speicheradresse meines Objekts an Temp übergeben. Durch freeandnil wird der Speicherbereich meines Objekts freigegeben. und demnach sollte dann auch
workarray[0]=nil true liefern und keine AV.
Wo genau ist da jetzt mein Fehler?
Gruß
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#23

Re: untypisierter pointer

  Alt 20. Jan 2005, 13:16
Moin!

Zitat von Jan:
In delphi sind doch meines Wissens nach Variabeln auch nichts anderes als Zeiger auf einen Speicherinhalt.
Jede Instanzenvariable ist nur ein Zeiger auf das eigentliche Objekt (besser: die eigentliche Objektinstanz). Dieses trifft nicht für eine Variable vom Typ Integer, Record oder sonstiges zu - Ausnahme dabei sind alle die definierten Typen, die bei der Definition ein ^ vor dem Typ tragen. Also z.B. ist ein PByte definiert als Type PByte = ^Byte; und somit ein Zeiger auf ein Byte. Bei irgendwelchen Variablen die Objekte sind, sind es automatisch Zeiger.

Zitat von Jan:
Und ist es nicht auch so, dass wenn ich zwei Objekte a und b habe, dass dann
Delphi-Quellcode:
a:=b;
a:=nil;
auch b nil setzt?
Nein, warum sollte? Wie oben schon geschrieben sind diese Variablen eigentlich ein Zeiger auf den Speicherbereich wo die Instanz des Objektes liegt - also eigentlich ein normaler Pointer. Daher läuft das so ab, das a auf einen Speicherbereich zeigt und b z.B. auf die ungültige Adresse 00000000h. Danach weisst er bei der Zuweisung b keine Referenz zu, sondern b zeigt dann einfach auf den gleichen Speicherbereich. Das ist so als wenn du einem Pointer einen anderen zuweist - danach zeigen beide auf den gleichen Speicherbereich. Beide Variablen (a und b) bieten Platz für eine 32 Bit Adresse (daher ergibt SizeOf(a) bei beiden jeweils 4 Byte) - und beide haben ihren eigenen Speicherplatz von 4 Byte wo die sich diese Adresse drin merken. a liegt z.B. an Speicherstelle X und enthält als Adresse die Adresse einer Objektinstanz TT. Nun liegt Variable b an der Speicherstelle Y und enthält 0. Bei der Zuweisung werden einfach die 4 Byte der Variablen an der Speicherstelle Y mit dem gleichen Inhalt wie den der Speicherstelle X gleich gesetzt - also einmal umkopiert. Wenn du nun a Nil zuweist, dann wird in Speicherstelle X einfach eine 0 reingeschrieben - aber die Speicherstelle Y ist das doch egal - die hat nix mit a oder Speicherstelle X zu tun. Daher enthält danach die Speicherstelle Y immernoch den gleichen Inhalt.

Beispiel:
Delphi-Quellcode:
program TestReference;
{$APPTYPE CONSOLE}

uses sysutils;

Var
  a, b : TObject;

begin
  WriteLn('Objekte - Zuweisungsspiele');

  a := Nil;
  b := Nil;

  WriteLn('a = 0x', IntToHex(Integer(a), 8), ' b = 0x', IntToHex(Integer(b), 8));

  a := TObject.Create;

  WriteLn('a = 0x', IntToHex(Integer(a), 8), ' b = 0x', IntToHex(Integer(b), 8));

  b := a;

  WriteLn('a = 0x', IntToHex(Integer(a), 8), ' b = 0x', IntToHex(Integer(b), 8));

  FreeAndNil(a);

  WriteLn('a = 0x', IntToHex(Integer(a), 8), ' b = 0x', IntToHex(Integer(b), 8));

  ReadLn;
end.
Zitat von Jan:
Und nach dem Prinzip dachte ich würde auch das funktionieren:

Delphi-Quellcode:
temp:=tstringlist(listview1.selected.data);
      freeandnil(temp);
Data ist ein Zeiger, und jetzt wird die Speicheradresse meines Objekts an Temp übergeben. Durch freeandnil wird der Speicherbereich meines Objekts freigegeben.
Richtig - du schreibst es selber richtig - die Speicheradresse wird übergeben - also nur die Adresse wo der Inhalt liegt.

Zitat von Jan:
und demnach sollte dann auch
workarray[0]=nil true liefern und keine AV.
Wo genau ist da jetzt mein Fehler?
Der liegt genau an dem Punkt zu erkennen (bzw. mir zu glauben ), dass Data von der ListView1.Selected einen eigenen Speicherplatz für diese Adresse vorhält auf die er zeigt wie Temp - der auch seinen eigenen Speicherplatz für die Adresse vorhält. Nach der Zuweisung beinhalten aber beide Speicherplätze die selbe Zahl (Adresse), aber sie liegen an unterschiedlichen Stellen.

Wenn da immer Referenzen übergeben werden würden, dann müsste man ja mehr als höllisch aufpassen - wenn du dir irgendwo eine Zahl veränderst, an wieviel anderen Stellen auf einmal auch eine andere Zahl drinne steht.

MfG
Muetze1
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#24

Re: untypisierter pointer

  Alt 20. Jan 2005, 13:39
Hallo Muetze1,
erstmal vielen Dank für deine ausführliche und geduldige Antwort auf mein Problem, das ist nämlich wirklich der einzige verbleibende Bug bevor ich das Programm endlich posten kann.

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.

Nur ist aber meine Frage: warum klappt folgendes nicht:

Delphi-Quellcode:
      temp:=tstringlist(listview1.selected.data);
      freeandnil(temp);
      showmessage(workarray[0].strings[0]);
Ohne freeandnil gibt showmessage den gewünschten string an, aber mit freeandnil bekomme ich eine AV, weil wohl anscheinend die Stringlist auf die ich zugreife nichtmehr existiert.
Das ist ja eigentlich genau was ich will, aber trotzdem klappt die Abfrage ob workarray[0] nil ist nicht.
Ich habe hier massive Verständnisschwierigkeiten.

Gruß
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#25

Re: untypisierter pointer

  Alt 20. Jan 2005, 17:19
Kann mir denn dabei wirklich keiner Helfen?
Müsste doch für die vielen erfahrenen Programmierer hier kein Problem sein, oder?
Gruß
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#26

Re: untypisierter pointer

  Alt 20. Jan 2005, 22:41
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*
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#27

Re: untypisierter pointer

  Alt 20. Jan 2005, 23:51
Wow!
Also deine Bemühungen sind echt bemerkenswert, so eine Antwort hab ich noch nie bekommen.
Aber, ohne dich jetzt enttäuschen zu wollen, es hätte wirklich gereicht mir zu sagen, dass freeandnil sowohl den Speicherbereich für die Variable, als auch den Speicherbereich für das Objekt, auf welches die Variable zeigt löscht, oder irgendwie auf was anderes setzt. Das wusste ich nämlich nicht. Jetzt ist mir auch klar, warum die Abfrage auf nil beim array[0] nicht funktioniert.
Aber eine ganz klasse Antwort hast du geschrieben. Danke!
Gut.. jetzt weiss ich warum das ganze nicht klappt, aber was kann ich dagegen machen? wie prüfe ich jetzt, ob workarray[0] noch auf ein gültiges TStringlist Objekt im Speicher zeigt, oder nicht? einfach ausprobieren und dann exception abfangen?
Ich habe versucht die Variable zu dereferenzieren und dann auf nil abzufragen, aber das mag Delphi verständlicher Weise nicht. Und da weiß ich dann auch schon nichtmehr weiter.
Gruß
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.105 Beiträge
 
Delphi 11 Alexandria
 
#28

Re: untypisierter pointer

  Alt 21. Jan 2005, 00:37
Moin Jan,

Zitat von Jan:
dass freeandnil sowohl den Speicherbereich für die Variable, als auch den Speicherbereich für das Objekt, auf welches die Variable zeigt löscht,
nur dass Du es nicht missverstanden hast:
Es wird das Objekt freigegeben, auf das der Pointer, den die Variable enthält, zeigt.
Der Inhalt der Variablen wird auf nil gesetzt.

Der Speicherbereich für die Variable selbst bleibt davon unberührt.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz