IsMemory, FreeMemoryEx

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

IsMemory, FreeMemoryEx

Beitrag von Sicro »

Code: Alles auswählen

;   Description: Adds the function 'IsMemory()' (works like IsFile() etc.)
;        Author: Sicro
;          Date: 2017-06-09
;            OS: Windows, Linux, Mac
; English-Forum: Not in the forum
;  French-Forum: Not in the forum
;  German-Forum: Not in the forum
; -----------------------------------------------------------------------------

Global NewMap MemoryAddresses()

Procedure.i _AllocateMemory(Size, Flags=0)

  Protected *Memory = AllocateMemory(Size, Flags)
  If *Memory
    MemoryAddresses(Str(*Memory)) = #True
  EndIf
  ProcedureReturn *Memory

EndProcedure

Procedure.i _ReAllocateMemory(*Memory, Size, Flags=0)

  Protected *NewMemory = ReAllocateMemory(*Memory, Size, Flags)
  If *NewMemory
    DeleteMapElement(MemoryAddresses(), Str(*Memory))
    MemoryAddresses(Str(*NewMemory)) = #True
  EndIf
  ProcedureReturn *NewMemory

EndProcedure

Procedure _FreeMemory(*Memory)
  FreeMemory(*Memory)
  DeleteMapElement(MemoryAddresses(), Str(*Memory))
EndProcedure

Macro AllocateMemory(Size, Flags=0)
  _AllocateMemory(Size, Flags)
EndMacro

Macro ReAllocateMemory(Memory, Size, Flags=0)
  _ReAllocateMemory(Memory, Size, Flags)
EndMacro

Macro IsMemory(Memory)
  MemoryAddresses(Str(Memory))
EndMacro

Macro FreeMemory(Memory)
  _FreeMemory(Memory)
EndMacro

;-Example
CompilerIf #PB_Compiler_IsMainFile

  Define *Memory1, *Memory2, *Memory2_resized
  
  *Memory1 = AllocateMemory(4*1024)
  *Memory2 = AllocateMemory(8*1024)
  If *Memory1 = 0 Or *Memory2 = 0
    Debug "Error: AllocateMemory()"
    End
  EndIf
  
  Debug "IsMemory(Memory1): " + IsMemory(*Memory1)
  Debug "IsMemory(Memory2): " + IsMemory(*Memory2)
  Debug "---------------------------------------"
  Debug "Free Memory1"
  FreeMemory(*Memory1)
  Debug "---------------------------------------"
  Debug "IsMemory(Memory1): " + IsMemory(*Memory1)
  Debug "IsMemory(Memory2): " + IsMemory(*Memory2)
  
  Debug ""
  Debug "======================================="
  Debug ""
  
  Debug "MemorySize(Memory2): " + MemorySize(*Memory2)
  Debug "---------------------------------------"
  Debug "Resize Memory2"
  Debug "---------------------------------------"
  *Memory2_resized = ReAllocateMemory(*Memory2, 16*1024)
  If *Memory2_resized
    *Memory2 = *Memory2_resized
    Debug "MemorySize(Memory2): " + MemorySize(*Memory2)
  EndIf
  
  Debug ""
  Debug "======================================="
  Debug ""
  
  Debug "IsMemory(Memory1): " + IsMemory(*Memory1)
  Debug "IsMemory(Memory2): " + IsMemory(*Memory2)
  Debug "---------------------------------------"
  Debug "Free Memory2"
  FreeMemory(*Memory2)
  Debug "---------------------------------------"
  Debug "IsMemory(Memory1): " + IsMemory(*Memory1)
  Debug "IsMemory(Memory2): " + IsMemory(*Memory2)

CompilerEndIf
Temporäre CodeArchiv-Adresse: https://github.com/SicroAtGit/PureBasic ... Memory.pbi

Code: Alles auswählen

;   Description: Extends PB-FreeMemory so that it also nulls the address variable
;        Author: Sicro
;          Date: 2017-06-09
;            OS: Windows, Linux, Mac
; English-Forum: Not in the forum
;  French-Forum: Not in the forum
;  German-Forum: Not in the forum
; -----------------------------------------------------------------------------

Procedure _FreeMemory(*Memory)

  FreeMemory(PeekI(*Memory))
  PokeI(*Memory, 0)

EndProcedure

Macro FreeMemory(Memory)
  _FreeMemory(@Memory)
EndMacro

;-Example
CompilerIf #PB_Compiler_IsMainFile

  Define *Memory = AllocateMemory(1024)
  If *Memory = 0
    Debug "Error: AllocateMemory()"
    End
  EndIf
  
  Debug "Memory: " + *Memory
  Debug "---------------------"
  Debug "Free Memory"
  FreeMemory(*Memory)
  Debug "---------------------"
  Debug "Memory: " + *Memory

CompilerEndIf
Temporäre CodeArchiv-Adresse: https://github.com/SicroAtGit/PureBasic ... moryEx.pbi

Eure Meinungen zu den obigen Codes sind erwünscht. Ich bin noch unentschlossen, ob ich sie endgültig ins CodeArchiv aufnehmen soll.
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
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: IsMemory, FreeMemoryEx

Beitrag von STARGÅTE »

Der erste Code ist in Ordnung.
Mit dem zweiten bin ich unzufrieden.

Ersten ist es für später "verwirrend" wenn Leute "dein" FreeMemory(*Memory) sehen und erst mal nicht sehen würden, dass *Memory auf Null gesetzt wird.

Der zweite Code geht vor allem dann schief, wenn die Nutzer versuchen eine Funktion als Parameter zu übergeben:

Code: Alles auswählen

FreeMemory(IrgendeineFunktion(Parameter))
Statt dessen, könntest du vllt "dein" FreeMemory immer 0 zurückgeben lassen und dann kann man einfach *Memory = FreeMemory(*Memory) nutzen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: IsMemory, FreeMemoryEx

Beitrag von Sicro »

Danke STARGÅTE


Codes wurden aktualisiert:

IsMemory:
  • Mutex-Befehle hinzugefügt, um die sichere Verwendung innerhalb von Threads zu gewährleisten
STARGÅTE hat geschrieben:Ersten ist es für später "verwirrend" wenn Leute "dein" FreeMemory(*Memory) sehen und erst mal nicht sehen würden, dass *Memory auf Null gesetzt wird.
FreeMemoryEx:
  • Funktion von "FreeMemory()" zu "FreeMemoryEx()" umbenannt

    Es ist schlecht, wenn die PureBasic-Funktion durch eine neue Funktion ersetzt wird, die sich äußerlich anders verhält als die PureBasic-Funktion.
    Wenn vergessen wird, das Include zu integrieren, ist das nicht sofort offensichtlich erkennbar und kann zu schwer auffindbaren Fehlern führen.
STARGÅTE hat geschrieben:Der zweite Code geht vor allem dann schief, wenn die Nutzer versuchen eine Funktion als Parameter zu übergeben:

Code: Alles auswählen

FreeMemory(IrgendeineFunktion(Parameter))
Ich denke da bleibt uns nichts anderes übrig, als darauf hinzuweisen, dass keine Funktionen als Parameter übergeben werden dürfen.
STARGÅTE hat geschrieben:Statt dessen, könntest du vllt "dein" FreeMemory immer 0 zurückgeben lassen und dann kann man einfach *Memory = FreeMemory(*Memory) nutzen.
Bei dieser Funktionsweise wäre FreeMemoryEx() unnötig, weil die FreeMemory-Funktion von PB bereits immer "0" zurück gibt.


Die aktuellen Codes können über die Links betrachtet werden.
Die Codes im ersten Betrag des Threads werden erst aktualisiert, wenn die endgültigen Codes feststehen.
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
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: IsMemory, FreeMemoryEx

Beitrag von STARGÅTE »

Sicro hat geschrieben:Bei dieser Funktionsweise wäre FreeMemoryEx() unnötig, weil die FreeMemory-Funktion von PB bereits immer "0" zurück gibt.
Das mag zwar aktuell stimmen, ist jedoch nicht offiziell Dokumentiert. Zitat: "Diese Funktion gibt keinen Wert zurück."

Im übrigen ist mir noch n gute Idee eingefallen, wie du/man deine Include noch verwenden kann.
Da du ja nun eh dein eigenes AllocateMemory() hast, könntest du auch gleich noch n Funktion einbauen die am Ende alle "zu löschen vergessenen" Memorys auflistet.

Bei mir hieß eine solche Funktion MemoryReport() die man zB vor End aufruft.

In diesem Report, kannst du dann auch Datei, Zeilennummer, Procedure, Zeit, Größe usw. mitloggen, da du ja eh ein Macro verwendest:

Code: Alles auswählen

Macro AllocateMemory(Size, Flags=#Null)
	_AllocateMemory(Size, Flags, #PB_Compiler_File, #PB_Compiler_Procedure, #PB_Compiler_Line)
EndMacro
Diese Sachen kannst du dann in deiner Map mit abspeicher.
Diese Funktion kannst du dann per "CompilerIf #PB_Compiler_Debugger" entweder ignorieren (damit der Code nicht langsammer wird) oder eben ausführen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: IsMemory, FreeMemoryEx

Beitrag von Sicro »

STARGÅTE hat geschrieben:
Sicro hat geschrieben:Bei dieser Funktionsweise wäre FreeMemoryEx() unnötig, weil die FreeMemory-Funktion von PB bereits immer "0" zurück gibt.
Das mag zwar aktuell stimmen, ist jedoch nicht offiziell Dokumentiert. Zitat: "Diese Funktion gibt keinen Wert zurück."
Ja, hast recht. Es ist immer besser nur der offiziell dokumentierten Funktionsweise zu vertrauen. Ich habe die Funktion "FreeMemoryEx" nun so umgebaut, wie du es vorgeschlagen hast:
https://github.com/SicroAtGit/PureBasic ... moryEx.pbi
Danke! :)


Deine Idee für das Include "IsMemory" ist super. Ich bin derzeit noch am überlegen, wie ich diese Funktionalität einbaue, weil ich gerne die Themen "Memory" und "Debug" getrennt halten möchte. Deshalb habe ich die Include erst mal ohne diese Funktionalität ins "next"-Entwicklungszweig übernommen.

Was hältst du bzw. was haltet ihr von der Idee, eine weitere Debug-Include "ListAllocatedMemorys" zu erstellen, die abhängig von der Memory-Include "IsMemory" ist? Also die Include "CodeArchiv/Debug/ListAllocatedMemorys.pbi" würde die Include "CodeArchiv/Memory/IsMemory.pbi" benötigen.
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
Antworten