Richtiges Nutzen von AllocateMemory()

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Richtiges Nutzen von AllocateMemory()

Beitrag von diceman »

Hallo allerseits,
Ich habe mal wieder eine Noob-Frage ...
Und zwar habe ich in meiner ganzen Zeit mit PureBasic noch kein einziges Mal den Befehl "AllocateMemory()" benutzt ... ergo weiß ich auch gar nicht, was dieser überhaupt tut, und wie man ihn zweckmäßig nutzt, und ob er für meine Zwecke überhaupt relevant ist; ich sehe ihn aber andauernd in Beispiel-Codes im Forum und anderswo. Die F1-Hilfe ist mir bei meiner Frage keine große Hilfe, die ist sehr abstrakt und allgemein gehalten. Irgendwie wird Speicher reserviert, okay. Aber wie, warum, wozu? Und warum komme ich "trotzdem" klar, auch ohne den Befehl zu verwenden?
Ist das Speicher allokieren evtl. nur in Kombination mit "Peek" und "Poke" sinnvoll (beide noch nie verwendet) ... ? :|
Grafik-, Sound- und File-Operationen führe ich in meinen Applikationen dagegen am laufenden Band durch, ich nutze Structures und Listen, Pointer, "pass by reference" und "PB-Any". /:->
Aber irgendwie wurmt es mich schon, daß es da draußen ein weiteres Konzept gibt, daß ich ums Verrecken nicht verstehe, und was mir vielleicht dabei helfen könnte, noch effizienter und sauberer zu programmieren.
Vielen Dank!
Zuletzt geändert von diceman am 12.07.2019 11:48, insgesamt 1-mal geändert.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von NicTheQuick »

Wie ist denn deine Erfahrung mit Pointern? Wozu nutzt du sie? Normalerweise nutzt man die häufig auf Speicherbereichen, die man mit AllocateMemory oder AllocateStructure alloziert hat.

Vielleicht ein einfaches Beispiel: Du kannst eine Datei öffnen, mit Lof() die Dateigröße bestimmen, dann mit AllocateMemory() entsprechend viel Speicher allozieren und dann mit ReadData() die gesamte Datei in diesen Speicherbereich laden. Dann hast du die gesamte Datei im RAM und kannst mit Peek, Poke oder mit Pointern in diesem Speicherbereich Daten lesen und ändern.
AllocateMemory() reserviert also entsprechend viel Speicher im RAM deines PCs, in den du beliebig schreiben und wieder lesen kannst.
Bild
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von Bisonte »

AllocateMemory() reserviert einen Speicher für die eigene Nutzung.

Du hast "Pointer" ja schon genutzt, vermutlich sowas wie @MeineVariable oder @MeineListe().
Das ist im Grunde schon das gleiche. Allerdings ist das ganze flüchtig.

Wenn man z.B. einem Gadget mehr Daten mitgeben möchte, ohne eine List() oder Map() zu benutzen,
kann man das nur über einen reservierten Speicherbereich machen, da ansonsten der Speicher nach beenden
einer Prozedur z.B. nicht mehr existiert, bzw. keinen definierten Wert mehr besitzt.

Damit kann man dann per SetGadgetData(Gadget, *Speicher) dem Gadget jede Menge Daten "anhängen".
Am besten mit einer Struktur, damit das ganze bequemer zu füllen und auszulesen ist.

Beispiele :

Code: Alles auswählen

Structure myGadget
  Window.i
  Font.i
  Farbe.l
  Flag.l
EndStructure

*Speicher.myGadget = AllocateMemory(SizeOf(myGadget))
*Speicher\Farbe = #Red

SetGadgetData(Gadget, *Speicher)

*Speicher = GetGadgetData(Gadget)
Debug *Speicher\Farbe
Wobei mittlerweile das AllocateMemory() in Verbindung mit einer Struktur nicht mehr genommen wird, sondern
AllocateStructure(), da es gleich das InitializeStructure mitmacht (das auch Listen/Maps und Strings richtig initialisiert)
und nebenbei Schreibarbeit spart ;)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von diceman »

Ja vielen Dank, dann ist es doch schon etwas klarer geworden. :-)
In der Tat nutze ich *pointer primär in Zusammenhang mit Listen; z.B. um Elemente miteinander zu vergleichen, oder nach einem erneuten ForEach-Aufruf innerhalb einer ForEach-Schleife den ursprünglichen Zustand der ersten ForEach-Schleife wieder herzustellen, etc. Da muß man natürlich hin und wieder aufpassen, daß man mit ChangeCurrentElement nicht versucht, ein gerade gelöschtes Element wieder herzstellen, sonst gibt's Schläge vom Compiler.
Ich habe eine prägende Blitzbasic-Vergangenheit, daher gehören Strukturen und Listen für mich zwangsläufig zusammen, bzw. sobald ich eine Struktur deklariert habe, initialisiere ich sogleich eine zugehörige Liste um evtl. erstellte Elemente ordentlich verwalten zu können (hier schlägt PureBasic BlitzBasic um Längen, was Tools angeht, und der damit entstehende kreativer Spielraum).
Dann weiß ich jetzt zumindest, daß ich nichts falsch mache, bzw. es auch anders geht.
Und sollte ich tatsächlich mal tatsächlich in die Situation kommen sollte, daß ich eine komplette Datei in den Speicher laden muß, weiß ich, was ich dafür tun muß.
Zuletzt geändert von diceman am 12.07.2019 09:10, insgesamt 1-mal geändert.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von Sicro »

Mit AllocateMemory() hast du die Möglichkeit, darauf zu reagieren, wenn der Speicher nicht reserviert werden konnte:

Code: Alles auswählen

#KiB = 1024
#MiB = #KiB * 1024
#GiB = #MiB * 1024
*memory = AllocateMemory(40*#GiB)
If *memory
  PokeB(*memory + 10, 22) ; Write test
  FreeMemory(*memory)
Else
  Debug "Fehler: Speicher konnte nicht reserviert werden!"
EndIf
Hier eine Variante ohne AllocateMemory():

Code: Alles auswählen

#KiB = 1024
#MiB = #KiB * 1024
#GiB = #MiB * 1024
; Wie bei AllocateMemory() reservieren wir 40 GigaByte RAM:
Dim memory.b(40*#GiB)
memory(10) = 22 ; Write test     <= Ganzes Programm stürzt sofort ab!
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von Imhotheb »

Gibt es bei Dim einen Max-Wert?

Weil das hier:

Code: Alles auswählen

#KiB = 1024
#MiB = #KiB * 1024
#GiB = #MiB * 1024
*memory = AllocateMemory(40*#GiB)
If *memory
  Debug MemorySize(*memory)     ; 42949672960
  FreeMemory(*memory)
Else
  Debug "Fehler: Speicher konnte nicht reserviert werden!"
EndIf
korrekte 42949672960 ausgibt.

Dieser Code:

Code: Alles auswählen

#KiB = 1024
#MiB = #KiB * 1024
#GiB = #MiB * 1024
; Wie bei AllocateMemory() reservieren wir 40 GigaByte RAM:
Dim memory.b(40*#GiB)
Debug ArraySize(memory())     ; 0 ... sollte auch 42949672960 sein
aber nur 0.
weil einfach einfach einfach ist ... mach' ich es anders
Benutzeravatar
TroaX
Beiträge: 659
Registriert: 08.03.2013 14:27
Computerausstattung: PC: Ryzen 9 3950X, 96 GB RAM, RX6800XT, 2.5 TB SSD, 21:9 Display, Pop_OS! | Lappi: Ryzen 7 5800H, 16 GB RAM, 1 TB SSD, Pop_OS!
Wohnort: NRW
Kontaktdaten:

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von TroaX »

Für AllocateMemory gibt es viele Gründe. Grundsätzlich ist die Beschreibung in der Hilfe genau das, wie es auch zu beschreiben ist. Man reserviert einen Zusammenhängenden Speicherbereich. Dies ist aus verschiedenen Gründen nötig. Zum einen kann man in dem Speicher alles an Daten ablegen. Zum anderen kann man jedes erdenkliche Byte aus diesem Bereich abrufen oder ändern.

Es kommt immer auch darauf an, was man macht. Ich verwende es relativ häufig. Zum Beispiel beim Webserver, bei dem man nie weiß, wie groß die übertragenen Daten sind oder welchem Typ sie angehören. Oder allgemein Netzwerkgeschichten. Ich vermeide es auch gerne. Aber oftmals kommt man auch einfach nicht drum herum.
PC: Ryzen 9 3950X | 96 GB RAM | RX6800XT | 2,5 TB NVMe | Pop_OS!
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Pop_OS!
NAS: Fritz.Box :lol:
Coding: Purebasic 6.04 | PHP | HTML | CSS | Javascript
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von mk-soft »

Da man mit Pointer sich auch schnell vertun kann, hier eine Erweiterung im Debuggermodus

Code: Alles auswählen

;-TOP
;
; Memory Debugging v0.5

CompilerIf #PB_Compiler_Debugger
  
  #MemoryStop = 1
  
  Global NewMap MemID()
  
  Procedure MyAllocateMemory(Size, Flags, Proc.s)
    Protected *mem
    *mem = AllocateMemory(Size, Flags)
    If *mem
      MemID(Hex(*mem)) = *mem
    Else
      CompilerIf #MemoryStop
        If MessageRequester("AllocateMemory", "Out Of Memory : " + #LF$ + "Proc: " + Proc, 
                            #PB_MessageRequester_YesNo | #PB_MessageRequester_Error) = #PB_MessageRequester_No
          End
        EndIf
      CompilerElse
        DebuggerWarning("FreeMemory: Out Of Memory : " + Proc)
      CompilerEndIf
      ProcedureReturn #False
    EndIf
    ProcedureReturn *mem
  EndProcedure
  
  Procedure MyFreeMemory(Memory, Proc.s)
    If FindMapElement(MemID(), Hex(Memory))
      FreeMemory(Memory)
      DeleteMapElement(MemID())
      ProcedureReturn #True
    Else
      CompilerIf #MemoryStop
        If MessageRequester("FreeMemory", "Memory not exists : " + #LF$ + "Proc: " + Proc, 
                            #PB_MessageRequester_YesNo | #PB_MessageRequester_Error) = #PB_MessageRequester_No
          End
        EndIf
      CompilerElse
        DebuggerWarning("FreeMemory: Memory not exists : " + Proc)
      CompilerEndIf
      ProcedureReturn #False
    EndIf
  EndProcedure
  
  Procedure MyMemorySize(Memory, Proc.s)
    If FindMapElement(MemID(), Hex(Memory))
      ProcedureReturn MemorySize(Memory)
    Else
      CompilerIf #MemoryStop
        If MessageRequester("MemorySize", "Memory not exists : " + #LF$ + "Proc: " + Proc, 
                            #PB_MessageRequester_YesNo | #PB_MessageRequester_Error) = #PB_MessageRequester_No
          End
        EndIf
      CompilerElse
        DebuggerWarning("MemorySize: Memory not exists : " + Proc)
      CompilerEndIf
      ProcedureReturn 0
    EndIf
  EndProcedure
  
  Macro AllocateMemory(Size, Flags=0)
    MyAllocateMemory(Size, Flags, #PB_Compiler_Module + "/" + #PB_Compiler_Procedure + "() - Line " + #PB_Compiler_Line)
  EndMacro
  
  Macro FreeMemory(Memory)
    MyFreeMemory(Memory, #PB_Compiler_Module + "/" + #PB_Compiler_Procedure + "() - Line " + #PB_Compiler_Line)
  EndMacro
  
  Macro MemorySize(Memory)
    MyMemorySize(Memory, #PB_Compiler_Module + "/" + #PB_Compiler_Procedure + "() - Line " + #PB_Compiler_Line)
  EndMacro
  
CompilerEndIf

;- test

Procedure Main()
  *mem1 = AllocateMemory(1024)
  ;*mem2 = AllocateMemory(2048)
  
  Debug "Size 1: " + MemorySize(*mem1)
  Debug "Size 2: " + MemorySize(*mem2)
  
  Debug "Free 1: " + FreeMemory(*mem1)
  Debug "Free 2: " + FreeMemory(*mem2)
EndProcedure : main()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Richtiges Nutzen von AllocateMemory()

Beitrag von diceman »

Danke für deine Mühe, den Code gucke ich mir nachher mal an. :)
Habe jetzt, glaube ich, selbst ein Beispiel gefunden, wo AllocateMemory() relevant für mich werden könnte, und zwar wenn ich mit ReceiveHTTPFile eine Seite aus dem Netz ziehe um diese z.B. nach Keywords zu durchforsten, müßte ich Speicher reservieren, in denen ich die Website-Daten ablegen kann, bevor ich irgend etwas Sinnvolles mit dem File anstellen kann ...
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Antworten