Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Pointer, Arbeitsspeicher etc.. (https://www.delphipraxis.net/57435-pointer-arbeitsspeicher-etc.html)

Neutral General 21. Nov 2005 11:47


Pointer, Arbeitsspeicher etc..
 
Hi,

Ich wollte den String auslesen der an einer bestimmten Speicheradresse liegt.

So

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var Hallo: Pointer;
    bla: String;
begin
Instanz := TKlasse.Create;
Instanz.Eigenschaft := 'Hallo';
Hallo := GetMemory($00403EB0); // an der Adresse müsste Instanz.Eingeschaft sein
SetLength(bla,sizeof(Integer));
bla := String(@Hallo);
ListBox1.Items.Add(bla);
end;
Da kommt jedoch nur kryptische Zeichen xD
Ist GetMemory dafür überhaupt geeignet ?
Und ich habe die Adresse herausgefunden indem ich z.B Caption := Instanz.Eigenschaft geschrieben habe bevor die Klasse erstellt wurde. Die Adresse von der Zugriffsverletzung hab ich dann genommen. Bin mir aber auch nicht sicher ob das so geht :mrgreen:

Ach ja noch was wodrauf ich gestoßen bin, was ich sehr komisch fand:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var Hallo: Pointer;
    bla: String;
begin
Instanz := TKlasse.Create;
Instanz.Eigenschaft := 'Hallo';
Hallo := GetMemory($00403EB0); // Da müsste 'Hallo' gespeichert sein
Form1.Font.Name := (String(@Hallo));
SetLength(bla,sizeof(Integer));
ListBox1.Items.Add(bla);
end;
Das ist eine seltsame Erscheinung finde ich. Also wenn ich das so da stehen hab steht in der Listbox "comc"
Aber woher kommt das ? Ich hab Bla doch gar nix zugewiesen^^
Wenn ich schreibe

Delphi-Quellcode:
Caption := (String(@Hallo));
dann steht in der ListBox "Form".. komisch. :gruebel:
Vielleicht auch nur komisch weil ich von Pointern mal (fast) keine Ahnung hab :D

Luckie 21. Nov 2005 11:54

Re: Pointer, Arbeitsspeicher etc..
 
Delphi-Referenz durchsuchenGetMemory alloziiert dir nur Speicher, wie auch ein Blick in die Hilfe es dir gesagt hätte. Aber warum nutzt du nicht eine Methode / Property der Klasse, um dir den Wert zurückgeben zu lassen?

Neutral General 21. Nov 2005 11:58

Re: Pointer, Arbeitsspeicher etc..
 
Das war eigentlich nur ein Ansatz um ein Programm zu schreiben, das den ganzen Arbeitsspeicher auslesen soll.. Wenn das überhaupt geht..

Flocke 21. Nov 2005 12:08

Re: Pointer, Arbeitsspeicher etc..
 
Schreibe nicht
Delphi-Quellcode:
Hallo := GetMemory($00403EB0);
sondern einfach
Delphi-Quellcode:
Hallo := pointer($00403EB0);
(einfacher Typecast)

Neutral General 21. Nov 2005 12:10

Re: Pointer, Arbeitsspeicher etc..
 
Zitat:

Zitat von Flocke
Schreibe nicht
Delphi-Quellcode:
Hallo := GetMemory($00403EB0);
sondern einfach
Delphi-Quellcode:
Hallo := pointer($00403EB0);
(einfacher Typecast)

Ok und wie bekomme ich das dann in Klartext ausgegeben ? :mrgreen:

Neutral General 25. Nov 2005 13:01

Re: Pointer, Arbeitsspeicher etc..
 
*PUSH*

Also die Sache würde mich schon interessieren ;)

tigerman33 25. Nov 2005 14:13

Re: Pointer, Arbeitsspeicher etc..
 
Dann empfehle ich dir einen Blick in die Hilfe, zum Thema typisierte Zeiger und Dereferenzierung. :wink:

Neutral General 25. Nov 2005 14:18

Re: Pointer, Arbeitsspeicher etc..
 
Mh.. Also zu typisierte Zeiger hab ich nichts gefunden und das was bei Dereferenzierung steht bringt mich irgendwie auch nicht weiter :mrgreen:

tigerman33 25. Nov 2005 14:31

Re: Pointer, Arbeitsspeicher etc..
 
Donnerwetter, da findet die Hilfe tatsächlich nichts!! :shock:

Ein typisierter Zeiger ist ein Zeiger, der den Typ der Daten, auf die er verweist "kennt". Also z.B. ein Zeiger auf einen String, oder auf einen Integer. Deklariert wird das als
Delphi-Quellcode:
type TPInteger = ^integer;
Im Gegensatz dazu gibt es untypisierte Zeiger. Diesen Typ nennt man dann pointer.

Dereferenzieren bedeutet dass man die Daten erhalten will, auf die der Zeiger verweist. (Ein normaler Zugriff auf einen Zeiger liefert ja nicht dessen "Wert", sondern seine Speicheradresse!) Dereferenzieren kann man nur typisierte Zeiger (pointer muss man erst typecasten) denn nur diese wissen ja auf was sie eigentlich zeigen.

Muetze1 25. Nov 2005 14:35

Re: Pointer, Arbeitsspeicher etc..
 
Pointer: untypirisierter Zeiger, da es ein Zeiger ist (klar), aber ohne Angabe auf was er zeigt. Daher: der Typ auf den er zeigt ist unbestimmt. Somit kann man nicht ermitteln wie gross der Speicherbereich sein müsste um ein Element da abzulegen wo er hinzeigt.

Delphi-Quellcode:
Type
  TRGBQuad = Record
    rgbRed: Byte;
    rgbGreen: Byte;
    rgbBlue: Byte;
    rgbReserved: Byte;
  End;
  PRGBQuad = ^TRGBQuad;
PRGBQuad: typirisierter Zeiger, da es ein Zeiger auf eine Struktur vom Typ TRGBQuad handelt. Man weiss wie wo gross der Bereich ist, da man weiss wie gross die Struktur ist.

Delphi-Quellcode:
Var
  lMyPtr : PRGBQuad; // reserviert mir nur automatisch 4 Bytes um den Zeiger abzulegen - also da wo die Adresse von der Struktur später reinkommt.
Begin
    // bisher zeigt lMyPtr auf nix - bzw. ins Datennirwana (lokale Variable: sprich uninitialisiert)
    // es fehlt noch Speicherplatz für die Struktur, also erstmal alloziieren
  New(lMyPtr);
    // New() kann nur mit typirisierten Zeigern ohne weitere Angaben umgehen, da New() die Grösse zu reservierenden Speicher
    // ermitteln muss - und das geht nur mit typirisierten Zeigertypen.
   
  lMyPtr^.rgbRed := 124;  // hier dereferenziere ich
    // mit anderen Worten: ich will ja nicht auf den Zeiger zugreifen sondern auf den Speicherbereich auf den lMyPtr zeigt,
    // und dort dann ganz speziell auf den rgbRed Wert der Struktur - diese liegt ja in dem Bereich. Der Typ bringt
    // sozusagen Ordnung da rein und gibt mir die Möglichkeit bequem auf bestimmte Offsets innerhalb des Speicherbereichs zu
    // zu greifen. Und um nun zu sagen ich will nicht auf den Zeiger (lMyPtr) zugreifen sondern auf das, wo er hinzeigt,
    // dereferenziere ich ihn mit dem ^. (Nach dem Motto: sag mir nicht wo, sondern bring mich hin!)

    // so, auch in Beispielen sauber bleiben, also Speicher wieder freigeben den wir uns mit New() geholt hatten
  Dispose(lMyPtr)
End;
Einen untypirisierten Zeiger kann man mit dem ^ genauso dereferenzieren, aber da ist dann das Problem, das er (der Compiler) beim Zugriff nicht weiss, was nun alles zu dem Bereich gehört wo er hinzeigt. Das kann ein Byte, ein Array, eine Struktur oder sonstwas sein, daher meckert er im Normalfall - er weiss nicht damit umzugehen durch den fehlenden Typ. Du kannst ihm einen Typ zuweisen in dem du ihm sagst, das er auf ein Byte zeigt. Bsp:

Delphi-Quellcode:
Var
  lMyPtr : Pointer;
Begin
  GetMem(lMyPtr, 4); // 4 bytes reservieren und den Zeiger auf diese 4 Bytes zeigen lassen.
  lMyPtr^ := 22;   // Tja, wie gross ist der Datentyp??? Worauf zeigt er? Der Compiler streikt hier...
  PByte(lMyPtr)^ := 22; // so weiss er den Typ und weiss nun, es ist ein Byte gross und kann entsprechend zuweisen.

  FreeMem(lMyPtr, 4);
End;

Neutral General 25. Nov 2005 14:38

Re: Pointer, Arbeitsspeicher etc..
 
Oook ich habe das eiiiinigermaßen kapiert, ABER ich sehe keinen Vorteil in Zeigern.
Warum über einen Zeiger irgendwo drauf zugreifen wenns auch "normal" geht ?

Wobei diese Frage wahrscheinlich zeigt das ichs doch nicht kapiert hab :mrgreen:

tigerman33 25. Nov 2005 14:50

Re: Pointer, Arbeitsspeicher etc..
 
Zeiger sind dann praktisch, wenn du sicherstellen willst, dass du die Änderung einer Variablen immer mitbekommst. Sagen wir, du hast zwei Variablen, a und b.
Wenn du jetzt willst, dass in b das gleiche drinsteht wie in a, was tust du dann?
Vermutlich b := a;

So, wenn sich jetzt aber der Wert von a ändert, wird in b immer noch der alte Wert drinstehen. Dieses Problem kann man mit Zeigern lösen:

Delphi-Quellcode:
var a: integer;
    b: ^integer;

begin
  a := 5;
  b := @a; // Jetzt zeigt b auf die Stelle im Speicher, an der a steht
  // in b^ steht jetzt 5
  a := 3;
  // in b^ steht jetzt ebenfalls 3!
end;
Ein Nachteil von Zeigern ist, dass man ein bisschen mehr aufpassen muss, was man tut. Insbesondere reservierten Speicher wieder freizugeben, keine NIL-Zeiger zu dereferenzieren usw.

Neutral General 25. Nov 2005 14:52

Re: Pointer, Arbeitsspeicher etc..
 
ach sooooo. Ok. Aber das brauchte ich bis jetzt glaub ich kaum ^^
Naja danke, jetzt weiß ich wofür Zeiger gut sind :)

tigerman33 25. Nov 2005 14:56

Re: Pointer, Arbeitsspeicher etc..
 
Zitat:

Zitat von Neutral General
ach sooooo. Ok. Aber das brauchte ich bis jetzt glaub ich kaum ^^
Naja danke, jetzt weiß ich wofür Zeiger gut sind

Durch die Konzentration auf Klassen und Events braucht man Zeiger nicht mehr so oft. Früher kam man kaum ohne aus.

Allerdings "versteckt" Delphi viele Zeiger vor dir: Alle Objektinstanzen sind nämlich eigentlich Zeiger. Also eine Zeile der Form

Form1.Caption := ...

geht eigentlich nur durch CompilerMagic. Denn Form1 ist an und für sich ein Zeiger (auf das Objekt). Ohne Compilermagic müsste man den erst dereferenzieren. Das Objekte Zeiger sind ist wichtig im Hinterkopf zu behalten, wenn man solche Konstrukte baut:
Form1 := Form2;

Nicht nur dass jetzt der von Form2 belegte Speicher verloren ist, eine Änderung der einen Instanz wird immer auch bei einem Zugriff auf Form2 "sichtbar" sein (da jetzt beide auf die selbe Instanz verweisen). Daher wird in TPersistent ja auch die Assign-Methode eingeführt.

Oxmyx 25. Nov 2005 15:16

Re: Pointer, Arbeitsspeicher etc..
 
Zitat:

Zitat von Neutral General
ach sooooo. Ok. Aber das brauchte ich bis jetzt glaub ich kaum ^^
Naja danke, jetzt weiß ich wofür Zeiger gut sind :)

Das ist wohl eher kaum der Hauptgrund, wieso es Zeiger gibt. Zeiger werden angewandt bei
a) dynamisch instanzierten Objekten
b) Strings
c) Arrays
d) höhere Datenstrukturen wie z.B. verkettete Listen
e) Schnittstellen
...

Nur weil man sie meistens in Delphi nicht sieht, heißt das nicht, dass sie nicht da sind.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:52 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-2025 by Thomas Breitkreuz