![]() |
untypisierter pointer
Hallo DPler,
ich habe in meinem Programm ein TListview, dessen untereigenschaft tlistitem die Eigenschaft "Data" hat, welches ein untypisierter Zeiger auf ein Beliebiges Objekt ist. Über diese Eigenschaft habe ich jetzt die einzelnen Einträge meines Datenarrays verlinkt, (Array of Tstringlist) habe jetzt also einen untypisierten pointer auf ein Tstringlist Objekt. Jetzt muss ich zwei Dinge herausfinden: Wie kann ich das TStringlist Objekt auf nil setzen, und nicht den pointer, ohne dass ich eine Exception bekomme? Und 2.: gibt es eine Möglichkeit über den Zeiger auf das TStringlist Objekt irgendwie eine referenz auf den Array of Tstringlist zu bekommen, welcher das TStringlist Objekt beherbergt? Danke an alle die sich die Zeit nehmen das hier zu lesen! Gruß Jan |
Re: untypisierter pointer
Zitat:
du müsstest also auch die data property auf NIL setzten und dann mit assigend(data) abfragen Zitat:
poste mal nen code beispiel... dann ist es immer einfach tipps zu geben. grüße paresy |
Re: untypisierter pointer
Hallo,
Zitat:
Delphi-Quellcode:
Es kommt jetzt darauf an wie du das Objekt in das data geschrieben hast. Wenn dort ein Zeiger auf ein TStringList steht klappt das wie oben, wenn du einfach das Objekt umgecastet und reingeschrieben hast müßte folgendes gehen:
type
TMyFunnyArrayType = array of TStringList; PMyFunnyArrayPointer = ^TMyFunnyArrayType; //... PMyFunnyArrayPointer(lv.items[1].data)^ // <-------------------------------------> // Das ist jetzt vom Typ array of TStringList
Delphi-Quellcode:
Für einfach native Typen (die nur aus einem Schlüsselwort bestehen) kann man sich diese indirektionsstufe mit zusätzlichen Typen auch sparen.
TMyFunnyArrayType(lv.items[1].data)
// <-------------------------------------> // Das ist jetzt vom Typ array of TStringList |
Re: untypisierter pointer
Hallo Paresy!
Also du hast schon recht, das gibt eine exception, wenn man einen pointer dereferenziert, der auf ein nichtmehr vorhandenes Objekt zeigt. Aber ich hatte schlicht und einfach die Zuweisung des Pointers "data" falsch gemacht, so dass ein löschen eine exception hervorgerufen hat. Habe das aber durch ausführliches Beschäftigen mit pointern alles begradigen können. Das mit dem Zeiger auf den Array hat den Sinn, dass ich eine Prozedur habe, welche einen übergebenen array in ein Tlistview schreibt. Nun kann es aber vorkommen, dass der array nur eine auswahl von pointern auf objekte vom typ tstringlist innerhalb eines anderen arrays ist. Und ich will innerhalb dieser prozedur aber herausfinden wie groß der array ist, in dem die objekte und nicht die pointer enthalten sind. Eine weitere Verwendung ist, dass ich innerhalb des Tlistviews ein tlistitem löschen will. Es soll dann auch das objekt vom typ tstringlist gelöscht werden, auf welches der pointer "Data" von dem tlistitem zeigt. Dieses tstringlist objekt befindet sich in einem array of tstringlist. nachdem ich das element des arrays gelöscht habe, will ich aber auch die länge des arrays aktualisieren, daher brauche ich einen pointer auf den array. Hallo fiasko! Das codesegment was du da verfasst hast wandelt doch einen untypisierten Zeiger "data" in einen zeigre vom typ tstringlist um, oder irre ich? Wenn aber doch "data" ein Zeiger auf ein objekt vom typen tstringlist ist, was habe ich dann gewonnen? ich will ja einen zeiger auf ein anderes objekt haben (auf das übergeordnete array von dem tstringlist objekt), nicht einen typisierten zeiger auf das selbe objekt. Kann natürlich auch sein, dass ich unfug rede, aber ich kann das hier nicht ausprobieren, werde das machen, sobald ich zuhause bin. Danke euch beiden vielmals dass ihr euch damit befasst habt! Gruß Jan |
Re: untypisierter pointer
Hallo,
Zitat:
Zitat:
|
Re: untypisierter pointer
Hallo Fiasko!
Ich hab einen Array of tstringlist, der eine Filmliste speichert. Die einzelnen tstringlists speichern also jeweils einen Film. Ich habe jetzt einen Zeiger auf einen dieser Filme, will aber über diesen Zeiger irgendwie an einen Zeiger auf den Array of tstringlist kommen, in dem die Filme gespeichert sind, damit ich dort auslesen kann, wieviele Filme ich in der Filmliste habe. Gruß Jan |
Re: untypisierter pointer
Hallo,
das geht so nicht. Du kannst nicht schauen wo es überall einen Zeiger auf dein Objekt gibt, du mußt dir also selber irgendwo dein array of TStringList speichern. |
Re: untypisierter pointer
Hallo,
was bitte schön ist ein untypisierter Zeiger? Gibts auch typisierte Zeiger? Der Ausdruck ist schon in sich Quatsch! Rainer |
Re: untypisierter pointer
Moin!
Zitat:
Pointer = untypirisierter Zeiger - ein Zeiger auf Daten unbestimmten Typs und daher kann man auch nicht sagen wie gross die Daten sind auf die der Pointer zeigt. Daher kann man auch schlecht mit New() eine Variable des Typs Pointer anlegen lassen - man muss die Grösse angeben. PChar, PInteger, einfach ein Zeiger auf einen Typen: ^typ = typirisierter Zeiger. Wenn man diesen nutzt weiss der Compiler wie gross die Daten sind auf die der Zeiger zeigt und kann daher u.a. mit einem einfachen New() genügend Speicher reservieren. Und nun sag mir was daran Quatsch ist und was es daran nicht geben sollte... MfG Muetze1 |
Re: untypisierter pointer
Hallo,
Zitat:
Zitat:
|
Re: untypisierter pointer
Hallo,
ein Pointer ist nichts anderes als eine Adresse und sonst garnichts! Einem Pointer kann kein Mensch ansehen was an dieser Speicheradresse, auf die er zeigt steht! Aus diesem Grund ist der Ausdruck typisierter Pointer absoluter Quatsch! Rainer |
Re: untypisierter pointer
Und ein typisierter Pointer beinhaltet für den Compiler noch die Information um was für einen Typ von Daten es sich hinter der Adresse handelt auf die der Zeiger zeigt.
|
Re: untypisierter pointer
Hallo Luckie,
das möcht ich sehen. Hast du ein Stück Code? Oder gib mir ein Beispiel für einen "typisierten Pointer" Rainer |
Re: untypisierter pointer
Hallo,
Zitat:
Delphi-Quellcode:
var
tpoint: ^Int64; // Das nennt man einen typisierten, utpoint: Pointer; // das einen untypisierten Pointer! const a: array[0..6] of Int64 = (0,1,2,3,4,5,6); begin tpoint = @a; utpoint = @a; inc(tpoint); inc(utpoint); // hier sollte tpoint^ den Wert 1 und // Int64(utpoint^) den Wert 0 liefern. end |
Re: untypisierter pointer
Hallo runger,
Beispiele für typisierte Zeiger siehst du oben (z.B. im Beitrag von Muetze). Der Compiler prüft deshalb, ob bei einer Zuweisung an diesen Pointer auch der korrekte Typ verwendet wird, d.h. der Pointer zeigt immer auf Strukturen, die ihm vorher in der Definition bekannt gegeben wurde. Über den New Operator kann der Compiler auch feststellen, wieviel Speicherplatz er reservieren muss. |
Re: untypisierter pointer
Hallo,
wenn ihr das so seht OK. Vergesst mein Geschwätz! Danke Rainer |
Re: untypisierter pointer
Irgendwie werde ich den Verdacht nicht los, dass du sauer bist, dass es typisierte Pointer in Pascal gibt. :mrgreen:
Zitat:
|
Re: untypisierter pointer
Also gerade wenn ein Problem mit diesen unsäglichen Pointern behoben ist kommt das nächste:
Ich habe folgenden code:
Delphi-Quellcode:
temp ist vom typen tstringlist.
temp:=tstringlist(listview1.selected.data);
freeandnil(temp); if workarray[0]=nil then showmessage('bla'); data ist ein pointer auf ein tstringlist element des arrays workarray. workarray ist ein array vom typen tstringlist. Wenn ich jetzt zur Laufzeit den ersten Eintrag im Listview löschen will, also den workarray[0] dann soll der zeiger Data vom selektierten Listitem auf temp gespeichert werden, und dann freigegeben werden. Leider klappt aber die Abfrage
Delphi-Quellcode:
nicht. Allerding gibt ein Zugriff auf workarray[0] eine AV. Wie kann ich jetzt abfragen ob workarray[0] nun wirklich freigegeben wurde?
if workarray[0]=nil
Gruß Jan |
Re: untypisierter pointer
Moin!
Die AV kommt doch, weil er schon freigegeben wurde. Du musst nur noch das Array Element 0 löschen... MfG Muetze1 |
Re: untypisierter pointer
Hallo Muetze1,
natürlich bekomm ich eine AV, muss ja auch, es geht mir aber darum, dass ich bei workarray[0]=nil kein true rausbekomme, obwohl das Element ja freigegeben wurde. Wie kann ich also abfragen ob der workarray[i] freigegeben wurde? Gruß Jan |
Re: untypisierter pointer
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 |
Re: untypisierter pointer
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:
auch b nil setzt? weil doch bei
a:=b;
a:=nil;
Delphi-Quellcode:
lediglich eine Referenz auf b an a übergibt, oder irre ich da?
a:=b
Und nach dem Prinzip dachte ich würde auch das funktionieren:
Delphi-Quellcode:
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
temp:=tstringlist(listview1.selected.data);
freeandnil(temp);
Delphi-Quellcode:
true liefern und keine AV.
workarray[0]=nil
Wo genau ist da jetzt mein Fehler? Gruß Jan |
Re: untypisierter pointer
Moin!
Zitat:
Delphi-Quellcode:
und somit ein Zeiger auf ein Byte. Bei irgendwelchen Variablen die Objekte sind, sind es automatisch Zeiger.
Type PByte = ^Byte;
Zitat:
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:
Zitat:
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 |
Re: untypisierter pointer
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:
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.
temp:=tstringlist(listview1.selected.data);
freeandnil(temp); showmessage(workarray[0].strings[0]); 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 |
Re: untypisierter pointer
Kann mir denn dabei wirklich keiner Helfen?
Müsste doch für die vielen erfahrenen Programmierer hier kein Problem sein, oder? Gruß Jan |
Re: untypisierter pointer
Moin!
Zitat:
Zitat:
Zitat:
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 :wink: ). 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... :mrgreen: MfG Muetze1 PS: Die Story hat (c) - ich rede gerade mit einem Verleger über ein Zeiger-Kinderbuch... *g* |
Re: untypisierter pointer
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 |
Re: untypisierter pointer
Moin Jan,
Zitat:
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz