Page 1 of 1

Finding a memory leak

Posted: Thu Sep 17, 2009 3:45 pm
by milan1612
I've got quite some code here (~500 lines) and I know there's a memory leak somewhere in there.
I'm using these procedures here to detect memory leaks, but unfortunately, they can't guide
me to where the leaks actually happen.

Code: Select all

Global count = 0

Procedure AllocateMemory2(Size)
  count + size
  ProcedureReturn AllocateMemory(Size)
EndProcedure

Procedure FreeMemory2(Memory)
  count - MemorySize(Memory)
  FreeMemory(Memory)
EndProcedure

Procedure ReAllocateMemory2(Memory, Size)
  count + size - MemorySize(Memory)
  ProcedureReturn ReAllocateMemory(Memory, Size)
EndProcedure
What other tools do you use to find those nasty bastards in your code?
I already spend 2 hours scanning the code again and again...

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 5:37 pm
by Marco2007
How do you know, that there`s a leak?
Taskmanager?

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 5:46 pm
by milan1612
Marco2007 wrote:How do you know, that there`s a leak?
Taskmanager?
No, I use the functions I posted above to manage my memory allocations. If 'count' is not
zero after all deallocations, then there's a memory leak somewhere :wink:

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 6:07 pm
by Marco2007
Aha, what about using a ListIconGadget with 4 columns (Startaddress, BytesAdded, BytesRemoved, Diff)?

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 6:14 pm
by milan1612
That wouldn't be of any more use than the information I've already got. Somehow I
have to keep track where which allocation takes place and then in the end figure out
what memory I forgot to free. It's just that in my code I have several exit points, and
that doesn't exactly make things easier :|
Any ideas?

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 6:16 pm
by Trond
Maybe something like this?

Code: Select all

Structure SAllocation
  Size.i
  File.s
  Line.i
  Pointer.i
EndStructure

Global NewList Memories.SAllocation()

Procedure _AllocateMemory3(Size, File.s, Line.i)
  AddElement(Memories())
  Memories()\Size = Size
  Memories()\File = File
  Memories()\Line = Line
  Memories()\Pointer = AllocateMemory(Size)
  ProcedureReturn Memories()\Pointer
EndProcedure

Macro AllocateMemory3(Size)
  _AllocateMemory3(Size, #PB_Compiler_File, #PB_Compiler_Line)
EndMacro

Procedure FreeMemory3(Memory)
  ForEach Memories()
    If Memories()\Pointer = Memory
      DeleteElement(Memories())
      Break
    EndIf
  Next
  FreeMemory(Memory)
EndProcedure

Macro ReAllocateMemory3(Memory, Size)
  _ReAllocateMemory3(Memory, Size, #PB_Compiler_File, #PB_Compiler_Line)
EndMacro

Procedure _ReAllocateMemory3(Memory, Size, File.s, Line.i)
  ForEach Memories()
    If Memories()\Pointer = Memory
      DeleteElement(Memories())
      Break
    EndIf
  Next
  AddElement(Memories())
  Memories()\Size = Size
  Memories()\File = File
  Memories()\Line = Line
  Memories()\Pointer = ReAllocateMemory(Memory, Size)
  ProcedureReturn Memories()\Pointer
EndProcedure
I didn't test it, but it should keep track of all your allocations. When you think you have freed all your memory, open the variable viewer and view all items in the linked list memories. This will show you any remaining allocations, and in which file and on which line they were allocated.

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 6:16 pm
by DarkDragon
Well this was often discussed in the internet, because Linux has a tool named "valgrind". Google says to "valgrind windows" that there is no free alternative. And valgrind also just shows you which memory was freed and which not. Thats what you can do with your Memory procedures, too.

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 6:38 pm
by Marco2007
I just meant something like that (with 4 columns):

Code: Select all

Enumeration
  #Window
EndEnumeration

Enumeration
  #ListIcon
EndEnumeration

Global count = 0

Procedure AllocateMemory2(Size)
  count + size
  ProcedureReturn AllocateMemory(Size)
EndProcedure

Procedure FreeMemory2(Memory)
  count - MemorySize(Memory)
  For i=0 To CountGadgetItems(#listicon)-1 
    If GetGadgetItemText(#listicon, i, 0)=Str(memory)
      SetGadgetItemText(#ListIcon, i, Str(MemorySize(Memory)),2)
    EndIf
  SetGadgetItemText(#ListIcon, i, Str(Val(GetGadgetItemText(#ListIcon, i, 2))-Val(GetGadgetItemText(#ListIcon, i, 1))), 3)  
  Next
  FreeMemory(Memory)
EndProcedure

Procedure ReAllocateMemory2(Memory, Size)
  count + size - MemorySize(Memory)
  ProcedureReturn ReAllocateMemory(Memory, Size)
EndProcedure

Procedure memorywindow(mem, name.s)
AddGadgetItem(#ListIcon, -1, Str(mem)+Chr(10)+Str(MemorySize(mem))+Chr(10)+Chr(10)+Chr(10)+name)
EndProcedure

Procedure Open_Window()
If OpenWindow(#Window, 650, 182, 325, 305, "Memory",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
  ListIconGadget(#ListIcon, 20, 20, 275, 260, "Address", 50)
  AddGadgetColumn(#ListIcon, 1, "Add", 50)
  AddGadgetColumn(#ListIcon, 2, "Remove", 50)
  AddGadgetColumn(#ListIcon, 3, "Diff", 50)
  AddGadgetColumn(#ListIcon, 4, "Name", 60)
EndIf
EndProcedure

Open_Window()

*memory1=AllocateMemory2(200) : memorywindow(*memory1, "mem1")
*memory2=AllocateMemory2(400) : memorywindow(*memory2, "mem2")
*memory3=AllocateMemory2(600) : memorywindow(*memory3, "mem3")

FreeMemory2(*memory1)
FreeMemory2(*memory2)

Repeat: Until WaitWindowEvent()=#PB_Event_CloseWindow  
...just a code to demonstrate.

Re: Finding a memory leak

Posted: Thu Sep 17, 2009 7:28 pm
by milan1612
@Trond
Wow, this is bloody awesome. Took me 1 minute to find the location of the
leak and about 5 to fix it. This is great! Thanks a lot for this! :P

Re: Finding a memory leak

Posted: Sun Sep 20, 2009 11:51 pm
by Rescator
Ideally the IDE would have a Allocation viewer.