Seite 1 von 1

Memory Manager

Verfasst: 05.12.2010 20:39
von Josef Sniatecki
Hallo Community,

ich bin mir sicher, dass zu diesem Thema schon einige Codes und Bibliotheken zusammengestellt wurden,
doch ich habe mir trotzdem mal die Zeit genommen, ein Include aus meiner Sammlung für alle anderen
Ausführbar zu machen.

Hierbei handelt es sich um eine Sammlung von Befehlen, die zum Aufspüren von Speicherlücken im
sehr hilfreich ist. Man muss in seinem Quellcode nur folgende Quelldatei einbinden und
den Befehl "MemoryManagerDebugGarbage()" ausführen, damit das Aufspüren beginnen kann.

Features:
- Noch nicht gelöschte Speicherbereiche können eingesehen werden
- Für jeden Speicherbereich wird der Name der Prozedur vermerkt, die den Speicherbereich erstellt hat
- Zusätzlich kann man bestimmten Speicherbereichen eigene IDs zuweisen
- Man kann das automatische Debuggen deaktivieren
- Die Liste (eigentlich Map) der registrierten Speicherbereiche kann jederzeit geleert werden

Code: Alles auswählen

;**************************************************************
;    Memory manager
;  
;  Author: Josef Sniatecki
;**************************************************************



;******************************************
; Structures
;******************************************

Structure MemoryManagerEntry
  ProcedureName.s
  *Address
  Size.i
  ID.s
EndStructure



;******************************************
; Variables
;******************************************

Global NewMap MemoryManagerEntry.MemoryManagerEntry()
Global MemoryManagerEnableDebugging.i = #True
Global MemoryManagerID.i



;******************************************
; Declarations
;******************************************

Declare.i MemoryManagerAllocate(Size.i, Indentifier.s)
Declare.i MemoryManagerFree(*Memory)
Declare.i MemoryManagerFreeEntry(*Entry.MemoryManagerEntry)

Declare.i MemoryManagerReset()
Declare.i MemoryManagerEnableDebugging(State.i)
Declare.i MemoryManagerCount()
Declare.i MemoryManagerDebugGarbage()



;******************************************
; Functions
;******************************************

Procedure.i MemoryManagerAllocate(Size.i, Indentifier.s)
  Static *Address
  
  *Address = AllocateMemory(Size)
  AddMapElement(MemoryManagerEntry(), Str(*Address))
  
  MemoryManagerEntry()\Address = *Address
  MemoryManagerEntry()\Size    = Size
  
  If Indentifier
    MemoryManagerEntry()\ID = Indentifier
  Else
    MemoryManagerEntry()\ID = Str(MemoryManagerID)
    MemoryManagerID + 1
  EndIf
  
  ProcedureReturn *Address
EndProcedure
Procedure.i MemoryManagerFree(*Memory)
  FindMapElement(MemoryManagerEntry(), Str(*Memory))
  
  If MemoryManagerEnableDebugging
    Debug "Memory Manager: FREE <" + MemoryManagerEntry()\ID + ">"
    Debug "  CREATOR: " + MemoryManagerEntry()\ProcedureName
    Debug "  COUNT  : " + Str(MapSize(MemoryManagerEntry()) - 1)
  EndIf
  
  DeleteMapElement(MemoryManagerEntry())
  ProcedureReturn FreeMemory(*Memory)
EndProcedure

Procedure.i MemoryManagerReset()
  ClearMap(MemoryManagerEntry())
  MemoryManagerID = 0
EndProcedure
Procedure.i MemoryManagerEnableDebugging(State.i)
  MemoryManagerEnableDebugging = State
EndProcedure
Procedure.i MemoryManagerCount()
  ProcedureReturn MapSize(MemoryManagerEntry())
EndProcedure
Procedure.i MemoryManagerDebugGarbage()
  If MemoryManagerEnableDebugging
    ForEach MemoryManagerEntry()
      Debug "Memory Manager: LOST <" + MemoryManagerEntry()\ID + ">"
      Debug "  CREATOR: " + MemoryManagerEntry()\ProcedureName
      Debug "  ADDRESS: " + Str(MemoryManagerEntry()\Address)
      Debug "  SIZE   : " + Str(MemoryManagerEntry()\Size)
    Next
  EndIf
EndProcedure



Macro AllocateMemory(MemorySize, Indentifier = "")
  MemoryManagerAllocate(MemorySize, Indentifier)
  MemoryManagerEntry()\ProcedureName = #PB_Compiler_Procedure
  
  If MemoryManagerEnableDebugging
    Debug "Memory Manager: ALOC <" + MemoryManagerEntry()\ID + ">"
    Debug "  CREATOR: " + MemoryManagerEntry()\ProcedureName
    Debug "  COUNT  : " + Str(MapSize(MemoryManagerEntry()))
  EndIf
EndMacro
Macro FreeMemory(Memory)
  MemoryManagerFree(Memory)
EndMacro



;******************************************
; Beispiel
;******************************************

DisableExplicit

; Folgende Daten sollen uns nicht interessieren, da sie
; während der ganzen Ausführung erhalten bleiben:
MemoryManagerEnableDebugging(#False)

*PreA = AllocateMemory(4)
*PreB = AllocateMemory(4)
*PreC = AllocateMemory(4)

; Da uns die eben erstellten Daten später nicht interessieren,
; löschen wir sie aus der MemoryManager-Tabelle:
MemoryManagerReset()
MemoryManagerEnableDebugging(#True)

; Nun erstellen wir zwei Speicherbereiche:
*A = AllocateMemory(4)
*B = AllocateMemory(4)

; Ein Speicherbereich wird gelöscht:
FreeMemory(*A)

; Nehmen wir an, dass auch der restliche Speicher (*A) zu löschen war,
; so können wir das folgendermaßen überprüfen:
Debug "---------------"
MemoryManagerDebugGarbage()
Debug "---------------"

; Falls man bestimmte Speicherbereiche vermerken möchte,
; so kann dies getan werden:
*C = AllocateMemory(4, "'C'-Memory")

Debug "---------------"
MemoryManagerDebugGarbage()
Fragen, Verbesserungsvorschläge, Kommentare? Nur her damit :wink:

Gruß Josef