Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Pointer
Thomas_1110 - Di 24.06.03 20:04
Titel: Pointer
Hallo Forum
Eines was mich beschäftigt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| var Puffer: Pointer; begin GetMem(Puffer, 255); PChar(Puffer^) :='Testtext'; Showmessage(PChar(Puffer^)); Freemem(Puffer, 255); end; |
funktioniert.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| var Puffer: Pointer; begin GetMem(Puffer, 255); GetLogicalDriveStrings(255, PPuffer); Showmessage(PChar(Puffer^)); Freemem(Puffer, 255); end; |
gibt bei mir eine Fehlermeldung. ändere ich es so
Delphi-Quelltext
1:
| Showmessage(PChar(Puffer)); |
dann funktionierts.
Weiteres noch: wie kann ich aus Puffer am besten die einzelnen Strings auslesen. Verwende Delpie 3 pro.
Gruß Thomas
Moderiert von
Tino: Code- durch Delphi-Tags ersetzt.
AndyB - Di 24.06.03 20:25
| Zitat: |
| PChar(Puffer^) :='Testtext'; |
Weißt du, was du da machst? Anscheinend nicht, denn damit greiftst du auf einen Speicherbereich zu, dessen Adresse du durch das Konvertieren der ersten 4 Zeichen des neu reservierten Speichers in einen PChar erhältst. Das das zu einer Schutzverletzung führen sollte, ist dir doch klar. Aber anscheinend hast du Glück und somit eine Zeitbombe geschrieben.
Die richtige Konvertierung wäre PChar(Puffer) (ohne das "^"-Zeichen)
Thomas_1110 - Di 24.06.03 20:51
| Zitat: |
| Weißt du, was du da machst? Anscheinend nicht, denn damit greiftst du auf einen Speicherbereich zu, dessen Adresse du durch das Konvertieren der ersten 4 Zeichen des neu reservierten Speichers in einen PChar erhältst. |
Ist das nur bei PChar so oder auch bei anderen Typen?
| Zitat: |
| Die richtige Konvertierung wäre PChar(Puffer) (ohne das "^"-Zeichen) |
Komischerweise bekomme ich grad hier die Schutzverletzung :?: Wenn ich die Pointer richtig verstanden hab steht in Puffer die Adresse. Setzt ich ein ^ ran kann ich lesen und schreiben darin. Da in meinem Fall Puffer untypisiert ist, muß ich ihn vorher typisieren.
Also
das funktioniert jedenfalls bei mir
Gruß Thomas
AndyB - Di 24.06.03 21:13
Bei PChars kannst du nicht einfach den Zuweisungsoperator (":=") benutzen. Dieser würde nämlich die Zeiger-Adresse auf die Adresse setzen, an der der Compiler den String abgelegt hat.
Dein Code muss also
Delphi-Quelltext
1:
| StrCopy(PChar(Puffer), ''Testtext'); |
lauten.
Um noch einmal auf die Typenkonvertierung zurückzukommen.
Puffer -> $1000
An Speicheradresse $1000 steht: $00 01 02 03 04 05
Mit PChar(Puffer^) machst du nun folgendes:
Delphi-Quelltext
1: 2:
| var P: PChar; P := $00 01 02 03; |
Damit zeigt der neugewonnene Zeiger P nicht auf den reservierten Speicherplatz, sondern wild in den Arbeitsspeicher.
Bei
PChar(Puffer^) := 'Testtext'; überschreibst du die ersten 4 Bytes des Speichers, auf den Puffer zeigt. Dadurch wird aus den oben genannen
$00 01 02 03 die Adresse an der der Compiler 'Testtext' abgelegt hat. Es ist dann natürlich kar, dass du mit
ShowMessage(PChar(Puffer^)) die Adresse von 'Testtext' übergibst. Damit brauchst du gar nicht 255 Bytes reservieren, wenn du sowieso nur 4 davon nutzt.
Das 1. Beispiel kannst du auch so lösen:
Delphi-Quelltext
1: 2: 3: 4: 5:
| var Puffer: PChar; begin Puffer := 'Testtext'; ShowMessage(Puffer); end; |
Bei deinem 2. Beispiel machst du bei der Ausgabe den selben Fehler (vom Schreibfehler
PPuffer mal abgesene).
Die Funktion GetLogicalDriveStrings() schreibt die Daten in den ihr übergebenen PChar, wobei hier zu beachten ist, dass die einzelnen Teilstring mit einem #0-Zeichen von einander getrennt sind. Nach dem letzen Teilstring kommt ein #0#0, dass den gesamten String abschließt.
Wenn du nun PChar(Puffer) an ShowMessage übergibst, gibt diese nur den ersten Laufwerksbuchstaben aus, da das erste #0 als Stringende betrachtet wird. Das noch weitere Laufwerksbuchstaben folgen, kann ShowMessage nicht wissen. Dies muss der Programmierer erledigen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| var P: PChar; S: string; begin P := StrAlloc(255 + 1); try GetLogicalDriveStrings(255, P); while P^ <> #0 do begin SetString(S, P, StrLen(P)); P := StrEnd(P) + 1; ShowMessage(S); end; finally StrDispose(P); end; end; |
Thomas_1110 - Di 24.06.03 21:45
Danke für die Mühe, da muß ich noch viel lernen zum Thema Pointer :roll:
Bei deinem Beipiel muß man noch den Zeiger wieder auf den Ursprung setzten, sonst gibts am Schluß eine Fehlermeldung.
Gruß Thomas
Motzi - Fr 27.06.03 19:13
| Thomas_1110 hat folgendes geschrieben: |
| Danke für die Mühe, da muß ich noch viel lernen zum Thema Pointer :roll: |
Dann schau dir mal das Pointer-Tutorial an (hier in der Tutorial-Sparte).
@AndyB: was PChars und deren Typecastings betrifft so führt Delphi im Hintergrund oft noch zusätzliche Schritte aus! Bestes Beispiel sind die 3 verschiedenen Methoden einen String in einen PChar zu casten:
Delphi-Quelltext
1: 2: 3:
| PChar(String) @String[1] Pointer(String) |
mit jeder dieser Methoden kann man einen String in einen PChar casten, aber immer mit einem andren Ergebnis!
Thomas_1110 - Fr 27.06.03 20:16
| Zitat: |
| Dann schau dir mal das Pointer-Tutorial an (hier in der Tutorial-Sparte). |
Danke für den Tip, hab ich schon gelesen, ist aber nur ein Teil von dem was das Thema zu bieten hat.
Gruß Thomas
Motzi - Fr 27.06.03 20:25
Das stimmt schon, aber die wichtigsten Sachen werden darin bereits erklärt (referenzieren, dereferenzieren, ...) der Rest sind Details die man eh nur per learning by doing wirklich lernen kann...
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 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!