RAM-Adresse ermitteln

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
lzuser
Beiträge: 97
Registriert: Sa 20. Jun 2009, 16:00
OS, Lazarus, FPC: Win10 20H2, Laz 2.0.8 auch Linux Mint Mate 20, Laz 2.0.6
CPU-Target: 64Bit

RAM-Adresse ermitteln

Beitrag von lzuser »

Hallo,
ich habe zwei Variablen:

type tZeileZeiger=^string;
var Zeile:tZeileZeiger;
Zahl:integer;

begin
New(Zeile);
//RAM-Adressen, auf die Zeile und Zahl zeigen ???
Ausgabe1Edit.Text:=IntToStr(@Zeile); //funktioniert nicht
Ausgabe2Edit.Text:=IntToStr(@Zahl); //funktioniert nicht
end;

Über ein wenig Nachhilfe würde ich mich freuen.
Vielen Dank.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: RAM-Adresse ermitteln

Beitrag von theo »

Ist das Absicht, dass du das so kompliziert mit Zeigern machen willst?
Wenn ja, was soll das werden? Sieht ziemlich krank aus, das Ganze... :wink:

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: RAM-Adresse ermitteln

Beitrag von mse »

Die Compiler Fehlermeldung dürfte

Code: Alles auswählen

Error: Incompatible type for arg no. 1: Got "Pointer", expected "QWord"
lauten. Also:

Code: Alles auswählen

Ausgabe1Edit.Text:=IntToStr(ptruint(@Zeile));
Es gibt auch noch die Möglichkeit sedezimale Schreibweise zu verwenden:

Code: Alles auswählen

Ausgabe1Edit.Text:=IntToHex(ptruint(@Zeile),8); //oder 16 für 64 bit

lzuser
Beiträge: 97
Registriert: Sa 20. Jun 2009, 16:00
OS, Lazarus, FPC: Win10 20H2, Laz 2.0.8 auch Linux Mint Mate 20, Laz 2.0.6
CPU-Target: 64Bit

Re: RAM-Adresse ermitteln

Beitrag von lzuser »

theo hat geschrieben:Ist das Absicht, dass du das so kompliziert mit Zeigern machen willst?
Wenn ja, was soll das werden? Sieht ziemlich krank aus, das Ganze... :wink:
Danke für den hilfreichen Kommentar.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: RAM-Adresse ermitteln

Beitrag von theo »

lzuser hat geschrieben: Danke für den hilfreichen Kommentar.
War nicht böse gemeint. Ich denke nur, dass es besser wäre, auch zu beschreiben was man letztlich erreichen will.
S.a.: http://www.tty1.net/smart-questions_de.html#goal" onclick="window.open(this.href);return false;

lzuser
Beiträge: 97
Registriert: Sa 20. Jun 2009, 16:00
OS, Lazarus, FPC: Win10 20H2, Laz 2.0.8 auch Linux Mint Mate 20, Laz 2.0.6
CPU-Target: 64Bit

Re: RAM-Adresse ermitteln

Beitrag von lzuser »

theo hat geschrieben:
lzuser hat geschrieben: Danke für den hilfreichen Kommentar.
War nicht böse gemeint. Ich denke nur, dass es besser wäre, auch zu beschreiben was man letztlich erreichen will.
OK, dann frage ich dich auch gleich nochmal:
(Eine an mse abgeschickte Nachfrage kam irgendwie nicht an ???)

Ich möchte für eine Demo die Adressen im Stack und im Heap ermitteln.
Mein jetziger Stand:

type tZeileZeiger=^string;
var Zeile1,Zeile2:tZeileZeiger;

Folgende Befehle:

Code: Alles auswählen

//RAM-Adressen ermitteln:
MeldungenMemo.Lines.Add
  ('Zeile1 hat die RAM(Stack)-Adresse: '+IntToStr(ptruint(@Zeile1)));
MeldungenMemo.Lines.Add
  ('Zeile2 hat die RAM(Stack)-Adresse: '+IntToStr(ptruint(@Zeile2)));
MeldungenMemo.Lines.Add
  ('Zeile1 enthält als Zeiger die RAM(Heap)-Adresse: '+IntToStr(ptruint(Zeile1)));
MeldungenMemo.Lines.Add
  ('Zeile2 enthält als Zeiger die RAM(Heap)-Adresse: '+IntToStr(ptruint(Zeile2)));
ergeben:
ohne New(Zeile1) und New(Zeile2)
Zeile1 hat die RAM(Stack)-Adresse: 5786236
Zeile2 hat die RAM(Stack)-Adresse: 5786240
Zeile1 enthält als Zeiger die RAM(Heap)-Adresse: 0 (entspricht wohl NIL)
Zeile2 enthält als Zeiger die RAM(Heap)-Adresse: 0

nach New
Zeile1 hat die RAM(Stack)-Adresse: 5786236
Zeile2 hat die RAM(Stack)-Adresse: 5786240 (ist klar, weil ein Pointer 4byte belegt)
Zeile1 enthält als Zeiger die RAM(Heap)-Adresse: 450264
Zeile2 enthält als Zeiger die RAM(Heap)-Adresse: 450312 (ist noch nicht klar: 1 String=48byte????)
Zuletzt geändert von monta am Mo 9. Nov 2009, 13:20, insgesamt 1-mal geändert.
Grund: Highlighter

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: RAM-Adresse ermitteln

Beitrag von mse »

lzuser hat geschrieben: nach New
Zeile1 hat die RAM(Stack)-Adresse: 5786236
Zeile2 hat die RAM(Stack)-Adresse: 5786240 (ist klar, weil ein Pointer 4byte belegt)
Zeile1 enthält als Zeiger die RAM(Heap)-Adresse: 450264
Zeile2 enthält als Zeiger die RAM(Heap)-Adresse: 450312 (ist noch nicht klar: 1 String=48byte????)
new() bezieht Speicher vom memorymanager, wo der Block angelegt wird ist Sache des memorymangers und schwierig vorauszusehen.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: RAM-Adresse ermitteln

Beitrag von Socke »

Wenn du den Heap überwachen willst, solltest du dir einen eigenen Memory-Manger schreiben. Der bekommt immer mit, wenn Speicher angefordert oder freigegeben wird (du kannst einfach alles auf den alten MM durch reichen).

So, nun zu deinem Code:
Verwende doch bitte die Code-Tags, ist einfacher zu lesen.
Die Ausgabe von Speicheradressen wird üblicherweise in Hex ausgegeben, da dann alle gleich lang sind.
String ist bereits ein Zeiger und ein Zeiger auf einen Zeiger wird nur benötigt, wenn man einen Zeiger zurückgeben will (bspw. Callback/var-Parameter).
Wo die Strings im Heap abgelegt werden, sollte nicht dich sondern nur den Memory-Manager interessieren. Die 48 Byte Unterschied in der Adresse sind deshalb völlig in Ordnung (auch wenn mir nicht klar ist, was du mit einem Zeiger auf einen String bezwecken willst).

Sonstiges:
Sowohl Heap als auch Stack liegen im RAM. Wenn du das Wort "RAM" aus der Ausgabe entfernst, könnte das einfacher zu lesen sein.
Nach New() solltest du immer Dispose() aufrufen; sonst hast du Speicherleichen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: RAM-Adresse ermitteln

Beitrag von mschnell »

lzuser hat geschrieben:tZeileZeiger=^string;
Ich glaube nicht, dass ein Zeiger auf einen String das ist, was Du willst. Vermutlich willst Du ja einen Zeiger auf die Zeichen in einem String. Das ist ein pchar.

var p: pchar;
...

p:=pchar(mystring);

Vorsicht ! String ist "reference counted". wenn mystring jetzt "out of fokus" gerät, zeigt p auf nichts mehr.

pchar(mystring) ist dasselbe wie @mystring[1], aber nicht dasselbe wie @mystring !

-Michael

lzuser
Beiträge: 97
Registriert: Sa 20. Jun 2009, 16:00
OS, Lazarus, FPC: Win10 20H2, Laz 2.0.8 auch Linux Mint Mate 20, Laz 2.0.6
CPU-Target: 64Bit

Re: RAM-Adresse ermitteln

Beitrag von lzuser »

Socke hat geschrieben:Wenn du den Heap überwachen willst, solltest du dir einen eigenen Memory-Manger schreiben. Der bekommt immer mit, wenn Speicher angefordert oder freigegeben wird (du kannst einfach alles auf den alten MM durch reichen).
Das war nicht meine Absicht. Ich wollte nur eine Demo der Speicheradressen.
Socke hat geschrieben:Die Ausgabe von Speicheradressen wird üblicherweise in Hex ausgegeben, da dann alle gleich lang sind.
Das stimmt aber nicht bei meinen Ausgaben, oder?
Socke hat geschrieben:String ist bereits ein Zeiger und ein Zeiger auf einen Zeiger wird nur benötigt, wenn man einen Zeiger zurückgeben will (bspw. Callback/var-Parameter).
Ich hätte auch einen Zeiger auf irgend einen umfangreichen Adressdaten-Record nehmen können, war mir nur zu umständlich.
Socke hat geschrieben:Wo die Strings im Heap abgelegt werden, sollte nicht dich sondern nur den Memory-Manager interessieren.
Das tut es aber nun mal.
Socke hat geschrieben:Die 48 Byte Unterschied in der Adresse sind deshalb völlig in Ordnung.
Und genau dafür brauche ich noch eine Begründung: Warum liegen die beiden String-Speicher nur 48 Byte
auseinander, ich kann doch einen längeren String ohne Problem speichern und wieder lesen.
Wie macht das der Memory-Manger?
Socke hat geschrieben: Nach New() solltest du immer Dispose() aufrufen; sonst hast du Speicherleichen..
Klar!

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: RAM-Adresse ermitteln

Beitrag von Socke »

Um die Zahlen als Hexadezimal-String zu formatieren musst du statt IntToStr die Funktion IntToHex aufrufen.
Wie der Heap funktioniert, steht irgendwo in den Dokumentationen. Ich weiß nur noch, dass er intern wie ein Stack aufgebaut ist. Wenn du wissen willst, was genau gemacht wird, musst du den memory-Manger direkt befragen. Der Standard-Manager ist in der Datei rtl/inc/heap.inc der FPC-Quellen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: RAM-Adresse ermitteln

Beitrag von theo »

lzuser hat geschrieben: Und genau dafür brauche ich noch eine Begründung: Warum liegen die beiden String-Speicher nur 48 Byte
auseinander, ich kann doch einen längeren String ohne Problem speichern und wieder lesen.
Wie macht das der Memory-Manger?
Die AnsiStrings habe ja keine fixe Länge. Das hängt von deren Inhalt ab.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: RAM-Adresse ermitteln

Beitrag von mschnell »

lzuser hat geschrieben:Und genau dafür brauche ich noch eine Begründung: Warum liegen die beiden String-Speicher nur 48 Byte
auseinander, ich kann doch einen längeren String ohne Problem speichern und wieder lesen.
Der eigentliche "String" ist eine Struktur, die aus Referenzzähler, Länge und Pointer auf die Zeichenkette besteht 3*4 = 12 Bytes, die restlichen 36 Bytes sind andere Variablen, die auf dem Heap angelegt wurden, und/oder Overhead des Memory-Managers.

Der Pointer in der String-Struktur enthält die Adresse, die Du mit @MyString[1] oder pchar(MyString) bekommst. Beim Schreiben von Strings wird dieser Pointer u.U. verändert und der Speicher, auf den verwiesen wird unabhängig auf dem Heap dynamisch verwaltet.

Wenn Du übrigens

MyString1 := 'Hallo';
MyString2 := MyString1;

Machst, zeigen die Pointer beider Strings auf dieselbe Speicherstelle und 'Hallo' wird nur einmal auf dem Heap angelegt. Machst Du nun

MyString2[2] := 'x';

passiert ein "lazy copy".

-Michael
Zuletzt geändert von mschnell am Mo 9. Nov 2009, 09:26, insgesamt 3-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: RAM-Adresse ermitteln

Beitrag von mse »

Socke hat geschrieben:
Wie der Heap funktioniert, steht irgendwo in den Dokumentationen. Ich weiß nur noch, dass er intern wie ein Stack aufgebaut ist.
Nicht mehr, das war zu Turbo Pascal Zeiten. Da war der Heap ein zusammenhängender Block Ram der mit mark() und release() manipuliert werden konnte. Heute kann der Heap aus vielen, nicht zusammenhängenden Blöcken bestehen.
lzuser hat geschrieben:
Socke hat geschrieben:Die 48 Byte Unterschied in der Adresse sind deshalb völlig in Ordnung.
Und genau dafür brauche ich noch eine Begründung: Warum liegen die beiden String-Speicher nur 48 Byte
auseinander, ich kann doch einen längeren String ohne Problem speichern und wieder lesen.
Wie macht das der Memory-Manger?
Falls dein Testprogramm so aussieht:

Code: Alles auswählen

type 
 tZeileZeiger=^string;
var 
 Zeile1,Zeile2:tZeileZeiger;
begin
 [...]
 new(Zeile1);
 new(Zeile2);
 [...]
wird durch new(Zeile1) ein Speicherbereich des Typ tZeileZeiger^ = string reserviert und gegebenenfalls initialisiert. string = AnsiString im {$h+} Modus. Die Speichergrösse einer AnsiString-Variable ist die Grösse eines Pointers = 4 Byte in 32 Bit, siehe auch die Ausführungen vom mschnell. Nach new(Zeile1) sollte Pointer(Zeile1^) den Wert NIL zeigen, da referenzgezählte Variablen (AnsiString, WideString, dynamisches Array) mit null initialisiert werden.
Wie bereits mehrmals erwähnt, kann nicht davon ausgegangen werden, dass new() den Speicher in zusammenhängenden Bereichen anlegt. Fall du den Speicherbedarf einer Variable oder eines Typen wissen möchtest, benutze sizeof(). sizeof(zeile1^) liefert 4 auf 32Bit.

Antworten