Wie wende ich Ram (Memory) an?

Anfängerfragen zum Programmieren mit PureBasic.
D4uS1
Beiträge: 268
Registriert: 02.09.2006 12:16

Wie wende ich Ram (Memory) an?

Beitrag von D4uS1 »

Ich bin seit langem schon auf den Memory Bereich im Referenzhandbuch von PB gestoßen. Ich wüsste gerne wie man das ganze denn praktisch anwendet, wenn man zum Beispiel bestimmte Variablenwerte oder Bilder, wenn das überhaupt möglich ist, im Ram speichern will. Muss man einfach AllocateMemory(x) benutzen und dann nutzt PB den Speicher automatisch?
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

AllocateMemory() reserviert dir den Speicher im RAM.
Mit den Peek Funktionen kannst du Daten aus einem deiner selbst reservierten Speicherbereiche lesen,
mit den Poke Befehlen kannst du Daten in einen deiner selbst reservierten Speicher schreiben.

Beispiel mit Strings (mit Zahlen funktioniert das ähnlich):

Code: Alles auswählen

*speicher=AllocateMemory(1024) ; Wir reservieren 1024 Byte=1 KB Speicher im RAM

PokeS(*speicher, "St@andFurz") ; Wir speicher diesen String in *speicher

Debug PeekS(*speicher) ; Wir lesen den *speicher aus
Debug PeekS(*speicher, 5) ; Wir lesen nur die ersten 5 Zeichen aus *speicher

PokeS(*speicher, "Jedes Böhnchen gibt ein Tönchen") ; Wir überschreiben den *speicher

Debug PeekS(*speicher)

Warum reservieren wir 1 KB Speicher, wenn wir nur 9 Byte benutzen?
Nun, das ist wie beim Busunternehmen: Du mietest dir einen Bus für 50 Personen, aber an deiner Klassenfahrt nehmen nur 23 Schüler teil.

Der Rest bleibt einfach unbenutzt, bis du den Speicher überschreibst und dabei etwas längeres als zuvor reinschreibst.

Hinweis: Am Ende eines jeden Strings im RAM steht ein Chr(0), damit PureBasic weiß, wo dein String zuende ist.
Das ist vergleichbar mit dem Busfahrer: Der Bus bietet Platz für 50 Personen, es passen aber nur 49 rein, der Fahrer muss ja auch mit! Der Fahrer stellt also das Nullbyte (anderes Wort für Chr(0)) dar.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
D4uS1
Beiträge: 268
Registriert: 02.09.2006 12:16

Beitrag von D4uS1 »

macht das das Programm eigentlich wirklich so viel schneller?
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Das kommt ganz darauf an, was du machst, wie du ihn nutzt und wie viel du davon verstehst.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

'*Buffer = AllocateMemory(Size.l)' allokiert so viel Speicher, wie du willst.
Mit 'Size.l' gibst du die Größe in Bytes an, die du brauchst und '*Buffer'
enthält den Pointer (Zeiger, Speicheradresse) zum Speicherbereich.

Ich weiß jetzt nicht, was du mit deiner Frage "dann nutzt PB den Speicher
automatisch?" meinst, denn den Speicher willst du ja verwenden. Windows
(Linux, Mac) verwaltet den gesamten Speicher (RAM) und stellt ihn deinem
Programm nach Bedarf zur Verfügung.

Beispiel zum Laden einer Datei in einen Buffer (RAM) und Speichern in
einer anderen Datei.

Code: Alles auswählen

file_in.s = "c:\test1.txt"

If ReadFile(0, file_in) ;Datei laden
  Size.l = Lof(0)
  *buffer = AllocateMemory(Size) ;Speicher allokieren
  If *buffer
    ReadData(0, *buffer, Size) ;Datei auslesen
  EndIf
  CloseFile(0)
EndIf

If *buffer ;wenn Datei existiert
  file_out.s = "c:\test2.txt"
  If CreateFile(0, file_out) ;neue Datei erstellen oder alte überschreiben
    WriteData(0, *buffer, Size) ;Daten in Datei schreiben
    CloseFile(0)
  EndIf
  FreeMemory(*Buffer) ;Speicher wieder freigeben
EndIf
///Edit: Gott, bin ich langsam... /:->
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Kommt drauf an. In den meisten Fällen ja.
Mit Hilfe der Befehle PeekS() und PokeS() brauchst du Mid(), Left() und Right() gar nicht mehr.
Diese 3 befehle sind im Vergleich zu den Memorybefehlen sehr, sehr langsam.

Nehmen wir an, du hast einen String und möchtest nur die ersten 5 Zeichen haben, ich zeige dir, wie du es mit Left() und PeekS() machst:

Code: Alles auswählen

text$="StandFurz"

Debug Left(text$, 5) ; anfängerfreundlich, aber langsam
Debug PeekS(@text$, 5) ; für Fortgeschrittene, aber schnell
Variablen sind im Grunde nichts anderes als reservierter RAM, bloß dass PureBasic automatisch das reservieren und beschreiben des RAMs vornimmt. Man kann sich das so vorstellen:

Code: Alles auswählen

Define string$ ; entspricht AllocateMemory()

string$="tanga" ; entspricht PokeS()

Debug string$ ; entspricht PeekS()
Hast du dir im obigen Beispiel mal den Wert von *speicher angeschaut?

Code: Alles auswählen

Debug *speicher
Richtig, es ist eine Zahl, genauer: Die Adresse deines reservierten Speichers im RAM.

Das @-Zeichen vor string$ ermittelt die Adresse des Speichers von string$.

Code: Alles auswählen

Debug @string$
wird dir also auch eine Zahl anzeigen.

Sogar das hier ist möglich:

Code: Alles auswählen

Define string$ ; Reservieren des Speichers (das übernimmt PB)

string$=Space(10024) ; Wir bestimmen, wie groß der Speicher sein soll (1024 Byte)


; string$="tanga" ; So wollen wir diesmal nicht speichern!
PokeS(@string$, "tanga") ; sondern so :-)

; Debug string$ ; So wollen wir diesmal nicht kontrollieren
Debug PeekS(@string$) ; sondern so :-)


Du kannst, wie ich schon sagte, zum Beispiel auch Mid() durch einen PeekS() Befehl ersetzen. Das ist sehr viel schneller, vor allem je größer der String ist.
Doch dazu musst du wissen, was ein Offset ist. Eine genaue Übersetzung habe ich jetzt nicht, aber das ist ein "verschobener Bereich".

Um aus dem Wort PUREBASIC das Wort BAS heraus zu bekommen kannst du so vorgehen:

Code: Alles auswählen

string$="PUREBASIC"
Debug Mid(string$, 5, 3)
Oder so:

Code: Alles auswählen

*buffer=AllocateMemory(500) ; Diesmal nur 500 Byte reservieren
; Wir speichern PUREBASIC in den Speicher
PokeS(*buffer, "PUREBASIC")

; Wir wollen BAS haben
Debug PeekS(*buffer+5, 3)
*buffer ist diesmal nur eine andere Bezeichnung für *speicher.
Du erinnerst dich, *buffer ist in Wirklichkeit eine Zahl, die Adresse des Speichers.
Da jedes Zeichen von PUREBASIC genau 1 Byte lang ist, wir aber bei B anfangen wollen zu lesen müssen wir zum Wert von *buffer noch 5 zeichen hinzuaddieren.

Code: Alles auswählen

Debug PeekS(*buffer+5)
würde aber BASIC ausgeben, ohne den 2. Parameter liest PeekS() immer bis zum Ende des Speicherbereichs. Der 2. Parameter sagt, wie viele Bytes (also Zeichen) gelesen werden sollen, hier also 3.

Tada, wir erhalten BAS als Ergebnis.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Re: Wie wende ich Ram (Memory) an?

Beitrag von AND51 »

NickTheQuick hat geschrieben:Ich weiß jetzt nicht, was du mit deiner Frage "dann nutzt PB den Speicher automatisch?" meinst
Ich weiß, was du meinst.

Nein, PureBasic nutzt den Speicher nicht automatisch. Du kannst keinen Speicher mit AllocateMemory() reservieren und dann ganz normal wie bisher mit String-Variablen arbeiten.

Wenn du mit Speicherbereichen arbeiten willst, dann musst du auch PeekS() und PokeS() verwenden.


__________________________


Übrigens, ein sehr schönes Beispiel, wo Peek & Poke viel schneller sind, als Mid:
Beim Parsen. Wenn ich einen String habe und muss jedes Zeichen untersuchen, ob es ein A ist, kann ich ganz einfach Mid() nehmen, zeichen für Zeichen durchgehen... und 2 Stunden warten :lol:

Oder ich nehme PeekS() arbeite mit einem Offset. Ich schätze einfach mal grob, dass diese Methode 60% schneller als Mid() ist.

Wenn du später mal ganz der Profi bist, nimmst du (für diese spezielle Aufgabe) aber PeekC() anstatt PeekS() und sparst nochmal 15% Zeit.

Und wenn du irgendwann mal ein kleiner Bill Gates bist und dein eigenes OS proggst, arbeitest du mit mit der Character-Structur und pointerst. 8)

Nicht böse sein, aber bis dahin brauchst du noch ein bisschen - dann kannst du ja nene neuen Thread aufmachen. :allright:


_____________________________


Solltest du das mit dem Offset schon verstanden haben, stelle ich dir einfach mal eine Aufgabe:
Schreib mal eine Prozedur, die aus dem Wort PUREBASIC das A heraussucht.
Schreib also mal dein eigenes FindString("PUREBASIC", "A", 1). Wie gesagt, du kannst es erstmal einfach machen mit Mid() und dann steigst du auf PeekS() um.

Ich werde jetzt aber 2 Stunden weg sein, ehe ich wieder an den Rechner komme. Bis dahin, viel Erfolg. Die andere hier können dir ja auch helfen. :)
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

schon der zweite der mal zwei studen weg will...was isn heut abend los...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

<OT>
Kaeru Gaman hat geschrieben:schon der zweite der mal zwei studen weg will...was isn heut abend los...
Hausaufgaben ;-)

</OT>
a²+b²=mc²
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

<OT>
Ich erwerbe gerade die "Linzenz zum Tö... äh... Autofahren"
</OT>

@ Topic:
Hat sich bisher was getan? StandFurz? Der musste sicher auch zwei Stunden weg, Kaeru :lol:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Antworten