Entwickler-Ecke

Windows API - Inhalt einer bestimmten Adresse ändern


LastRide - Sa 05.07.08 21:58
Titel: Inhalt einer bestimmten Adresse ändern
Hi,

Ich habe mal eine Frage und zwar wollte ich gerne den Inhalt einer Adresse ändern. Dazu weiß ich ist es notwendig einen Zeiger zu definieren :stolzsei: xD.

Wenn ich das richtig Verstanden habe definiere Ich den Zeiger so


Delphi-Quelltext
1:
2:
var
  zeiger: ^TDaten;


Und wenn ich es jetzt weiter Richtig verstehe muss ich ihm im Heap Speicher reservieren was wie folgt funktioniert.


Delphi-Quelltext
1:
New(Zeiger);                    


Jetzt kommt aber der Punkt an dem ich nicht weiter weiß und zwar wie lege ich jetzt die Adresse auf den Zeiger, lese den Inhalt aus und veränder diesen dann?

Wäre euch sehr dankbar wenn mir da jemand auf die Sprünge helfen könnte.

MfG

LastRide


Tilman - Sa 05.07.08 22:05

Sobald du Speicher mit new reservierst, ist die Adresse auf dem Zeiger. Das machst du damit ja gerade ;)

Um nun den Inhalt zuzuweisen (und auszulesen) musst du dereferenzieren:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
 zeiger : ^Integer;

begin
  new(zeiger);
  zeiger^ := 5;
  ShowMessage(IntToStr(zeiger^));
  ..


LastRide - Sa 05.07.08 22:09

Das heißt ich setze für "5" jetzt einfach meine Adresse ein und schon wird mir der Inhalt angezeigt?

MfG LastRide

Edit: Ich habe falsch gedacht, sry. Wie Schaffe ich es denn dem Zeiger eine bestimmte Adresse zu Übergeben also nicht mit New(Zeiger) ihm seine eigene zu geben ?


Tilman - Sa 05.07.08 22:19

Mit dem @ Operator. (new brauchst du dann nicht) Beispiel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  daten: TMeineDaten;
  zeiger: ^TMeineDaten;
begin
  daten := TMeineDaten.Create;

  zeiger := @daten;   // zeiger zeigt jetzt auf daten


Wichtig: wenn man einen Zeiger auf eine Lokale Variable setzt, so muss man bedenken dass diese dann nach dem Funktionsaufruf wieder freigegeben wird. Soll der Zeiger auch nach dem Funktionsaufruf noch auf gütlige Daten zeigen, so muss der Speicherplatz entweder mit new reserviert werden, oder per @ auf eine Globale Variable gesetzt werden.

// edit:
Ürbigens, hier findest du ein Tutorial zum Thema "Pointer" dass kaum Wünsche übrig lässt:
http://www.manuel-poeter.de/index.php?site=tutorials


LastRide - Sa 05.07.08 22:28

Also zum Beispiel wennich auf die Adresse "04110BA4" zugreifen möchte einfach


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
begin

Zeiger := @04110BA4;
ShowMessage(IntToStr(Zeiger^));
Dispose(Zeiger);


end;


machen und das wars ?

MfG

LastRide


Tilman - Sa 05.07.08 22:32

Nein. Wenn du die Adresse hast (ungewöhnliche Vorgehensweise allerdings), musst du sie direkt angeben (mit Pointer und Integer casten), ohne @ davor. Allerdings, soweit ich weiß sind die Adressen die man hier bekommt unter Delphi keine echten Adressen. Möglicherweise funktioniert das also nicht so wie du dir das Vorstellst.

Beispiel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var
  str: String;

procedure TForm1.Button1Click(Sender: TObject);
var
 zeiger : ^String;

begin
  zeiger := Pointer(StrToInt(edit1.text));  // Zeiger zeigt jetzt auf die Adresse die in edit1 eingegeben wurde
  caption := zeiger^;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  edit1.Text := IntToStr(Integer(@str));  // edit1 zeigt die Adresse von str an
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  str := 'Hallo';
end;


Der Sinn dieses Beispieles ist natürlich gering.


LastRide - Sa 05.07.08 22:40

Ob gering oder nicht ;) es hilft mir weiter zu verstehen xD. Muss ich in deinem Beispiel also nur das hallo bei


Delphi-Quelltext
1:
 str := 'Hallo'                    


mit der Adresse Austauschen und fertig ist der Zeiger auf die Adresse ?

MfG

LastRide


Tilman - Sa 05.07.08 23:19

Fast ^^ du must den inhalt des editfeldes ändern (edit1.text) ^^


LastRide - So 06.07.08 11:50

Nachdem ich mir das pdf in deinem Link durch gelesen habe habe ich etwas bemerkt ;). Und ich denke das wir aneinander vorbei geredet haben :). Also nochmal zum Verständnis:


Delphi-Quelltext
1:
Zeiger := nil; // not in List                    


entspricht


Delphi-Quelltext
1:
Zeiger := $00000000;                    


kann ich dann nicht einfach bei der Adresse, ich verwende jetzt mal das Beispiel,


Delphi-Quelltext
1:
Zeiger := $04110BA4                    


den Code so abändern ?

MfG LastRide


Yogu - So 06.07.08 12:30

user profile iconLastRide hat folgendes geschrieben:
kann ich dann nicht einfach bei der Adresse, ich verwende jetzt mal das Beispiel,


Delphi-Quelltext
1:
Zeiger := $04110BA4                    


den Code so abändern ?

Nein, aber fast:


Delphi-Quelltext
1:
Zeiger := Pointer($04110BA4);                    

Du musst den Integer-Wert erst in einen Zeiger umwandeln.


LastRide - So 06.07.08 13:01

Okay damit ist meine Frage dann schon zum teil Beantwortet ;). Nur wie schaffe ich es jetzt den Wert auf den der Pointer zeigt auszulesen und zu ändern. Da wäre ich euch für eine Hilfe Stellung sehr verbunden.

MfG LastRide


Yogu - So 06.07.08 13:12

Das hat doch user profile iconTilman schon erklärt. Wenn du aber einen Zeiger ohne Typ hast, musst du ihn erst in einen typisierten Zeiger umwandeln:


Delphi-Quelltext
1:
PInteger(Zeiger)^ := 5;                    

Zuerst wird der untypisierte Zeiger in einen Zeiger auf einen Integer umgewandelt, dann dereferenziert und schließlich wird die 5 ins Ziel geschrieben. Natürlich musst du statt PInteger den gewünschten Zeigertyp eintragen.


uall@ogc - Mo 07.07.08 13:15

nehmen wir also an du hast einen Record der so aussieht:


Delphi-Quelltext
1:
2:
3:
4:
5:
  TPerson = packed record
    name: String[20];
    alter: byte;
  end;
  PPerson = ^TPerson;



und du weißt das an Adresse 0x00401000 so eine TPerson stehen soll dann macht man das so:


Delphi-Quelltext
1:
2:
3:
4:
5:
  var myPerson = PPerson;
  begin
    myPerson := Pointer($00401000);
    myPerson.Name := 'Peter';  // setzen
    if myPerson.Alter = 60 then  // abfragen


seit irgendeiner Delphi Version muss man das dref ^ nicht mehr angeben, wenns nicht gehen sollte:


Delphi-Quelltext
1:
2:
3:
4:
5:
  var myPerson = PPerson;
  begin
    myPerson := Pointer($00401000);
    myPerson^.Name := 'Peter';  // setzen
    if myPerson^.Alter = 60 then  // abfragen


Hidden - Mo 07.07.08 13:50

user profile iconuall@ogc hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  myPerson: PPerson;
begin
  myPerson := Pointer($00401000);
  myPerson.Name := 'Peter';  // setzen
  if myPerson.Alter = 60 then  // abfragen


packed bedeutet, dass die Daten in einem festen Block stehen müssen und nicht verteilt sein können, wie es auf der Festplatte manchmal der Fall ist :?:

kann es sein, dass es hier im Forum unheimlich viele Daniels gibt?^^


uall@ogc - Mo 07.07.08 15:11

packed bedeutet einfach, dass die Daten direkt hintereinander stehen und nicht zum Lese / Schreibzugriff optimiert sind (sondern um Speicher zu sparen), da Integers z.b. an einer durch 4 teilbaren Adresse schneller zu lesen sind (obwohl ich gerade auch meine Bedenkten habe, dass der Record auch dann im speicher mindestens bei einer durch 8 Teilbaren Adresse steht zwecks Standardalignment 8)