NoLeak - include to help you find memory leaks (PB5.20)

Share your advanced PureBasic knowledge/code with the community.
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by WilliamL »

Hi Luis!

I understand the concept but not much more than that. I suppose this could be useful in examining my programs. I am guessing that I would put the include reference in my program and read the results. Ok, what do the references mean. I ran your example on my Mac (yay, it worked!) and this is what I got. What does it mean in reference to your example? (imagine the data in columns :) )

Scope Name Size Current
Main NoLeak_FONT.T_NOLEAK_FONT() O -
Main NoLeak_ALLOC.T_NOLEAK_ALLOC() 4 3
Main NoLeak_IMAGE.T_NOLEAK_IMAGE() 7 6
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by gnasen »

It means that there are currently 0 fonts, 4 memory blocks and 7 images used, but not released. If you inspect the lists, it will say you in which source and line they have been allocated. If you for example create a new instance of whatever and delete it after that, the numbers should not change. If they increase, you have a leak :cry:

I found a little leak (at least 20bytes every minute) in my main program with this, thanks a lot!
pb 5.11
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by Fred »

just of curiosity, from where your leaks come from ?
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by gnasen »

Fred wrote:just of curiosity, from where your leaks come from ?
In my case I free every object (with all stuff it allocated) in a genereal "freeing procedure". However, there was one special case where I had to do a little workaround (cause of some pointer stuff, to avoid an IMA). And in this one case I skipped an If-block (the pointer was not longer available) in which I amongst other things freed a block of memory.
There error was, that the freeing should have been outside of this If-block.
pb 5.11
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by infratec »

Hi luis,

to make life easier I added a NoLeakDebug() procedure to the include file:

Code: Select all

Procedure DebugNoLeak()
  
  Shared NoLeak_FONT(), NoLeak_ALLOC(), NoLeak_IMAGE()
  Protected i
  
  i = 0
  
  If ListSize(NoLeak_FONT())
    Debug ""
    Debug "NoLeak Font:"
    Debug ""
    ForEach NoLeak_FONT()
      i + 1
      Debug "(" + Str(i) + ") " + "File: " + NoLeak_FONT()\sFile
      Debug "(" + Str(i) + ") " + "Line: " + Str(NoLeak_FONT()\iLine)
      Debug "(" + Str(i) + ") " + "ID: " + Str(NoLeak_FONT()\iFontNum)
      Debug "(" + Str(i) + ") " + "Name: " + NoLeak_FONT()\sName
      Debug "(" + Str(i) + ") " + "Size: " + Str(NoLeak_FONT()\iYsize)
      Debug ""
    Next
    Debug "----------------------------"
  EndIf
  
  If ListSize(NoLeak_ALLOC())
    Debug ""
    Debug "NoLeak Alloc:"
    Debug ""
    ForEach NoLeak_ALLOC()
      i + 1
      Debug "(" + Str(i) + ") " + "File: " + NoLeak_ALLOC()\sFile
      Debug "(" + Str(i) + ") " + "Line: " + Str(NoLeak_ALLOC()\iLine)
      Debug "(" + Str(i) + ") " + "Address: " + Str(NoLeak_ALLOC()\iAddress)
      Debug "(" + Str(i) + ") " + "Size: " + Str(NoLeak_ALLOC()\iBytes)
      Debug ""
    Next
    Debug "----------------------------"
  EndIf
  
  If ListSize(NoLeak_IMAGE())
    Debug ""
    Debug "NoLeak Image:"
    Debug ""
    ForEach NoLeak_IMAGE()
      i + 1
      Debug "(" + Str(i) + ") " + "File: " + NoLeak_IMAGE()\sFile
      Debug "(" + Str(i) + ") " + "Line: " + Str(NoLeak_IMAGE()\iLine)
      Debug "(" + Str(i) + ") " + "ID: " + Str(NoLeak_IMAGE()\iImageNum)
      Debug "(" + Str(i) + ") " + "Width: " + Str(NoLeak_IMAGE()\iWidth)
      Debug "(" + Str(i) + ") " + "Height: " + Str(NoLeak_IMAGE()\iHeight)
      Debug "(" + Str(i) + ") " + "Depth: " + Str(NoLeak_IMAGE()\iDepth)
      Debug ""
    Next
    Debug "----------------------------"
  EndIf    
  
  If i > 0
    Debug "NoLeak found " + Str(i) + " leaks!"
  Else
    Debug "NoLeak found no leaks!"
  EndIf
  
EndProcedure
CompilerElse
  Macro DebugNoLeak()
  EndMacro
Put the procedure code directly in front of the CompilerEndif.
Instead of

Code: Select all

CallDebugger ; press F12 here to inspect the NoLeak_*() lists
You can now use

Code: Select all

DebugNoLeak()
And you can left the DebugNoLeak() in your code. :mrgreen:

Bernd

@luis
If you want you can add it to your code, than I remove the code from here.
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by luis »

@WilliamL
gnasen already explained it (thanks), if you need more info just ask. Anyway if you go step by step in the example and then look at the results expanding the list contents should be all clear.

@infratec
I prefer to use the variable viewer but I put a link to your post in my first one.
"Have you tried turning it off and on again ?"
A little PureBasic review
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by WilliamL »

@gnasen - thanks for the explanation of the program output. I'm wondering if a memory leak can lead to an IMA which I have in my first program I wrote when pb became available to the Mac (many images in Procedures)? In this program (it seems) the variable values are overwritten which leads to IMAs.

@infratec - thanks for the code addition, it works fine and is a bit easier to read. I haven't figured out the 'expanding the list contents' part yet.

Hi Luis - thanks for the program. It was my understanding that when CreateImage was used the last image (of the same value) was automatically freed so no FreeImage was needed. I'm not sure where I read that but it appears to be wrong.

I hope this isn't a case of too much knowledge in the wrong hands. :)
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by luis »

WilliamL wrote: Hi Luis - thanks for the program. It was my understanding that when CreateImage was used the last image (of the same value) was automatically freed so no FreeImage was needed. I'm not sure where I read that but it appears to be wrong.
No you are right, and this code is wrong under this aspect.

According to the help:
help wrote: CreateImage(2, 640, 480) ; Create an image, the n°2
ResizeImage(2, 320, 240) ; Resize the n°2 image
CreateImage(2, 800, 800) ; Create a new image in the n°2 index, the old one is automatically free'ed
and
help wrote: The purpose of this section is to describe the behaviour, creation, and handling of objects in PureBasic. For the demonstration, we will use the Image object, but the same logic applies to all other PureBasic objects.
I never use static numbering in a real program, so I overlooked this (or better I forgot about it, not really relying on this behavior).

Indeed the include should be modified to accommodate that too, but I'm not 100% sure this automatic freeing always happen with any pb command involving pb objects.
"Have you tried turning it off and on again ?"
A little PureBasic review
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by WilliamL »

Luis,

Thanks for finding that for me, I sure couldn't remember where I saw that and was doubting my sanity! :?

I can't understand why you would use a Procedure to create an image then free it in the same procedure? What is the use of that? In my calendar program (for printing out) I have an image for each day that has many elements (such as moon/sunrise/picture background/holiday text/etc) that are all added for each day, in a procedure, and then the images are used to draw the calendar. When another month is created the whole process is repeated with the same image numbers. Is this going to cause a memory leak? I have generally used 'IsImage' before creating a new image and freeing the old image just to be on the safe side.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by luis »

WilliamL wrote: I can't understand why you would use a Procedure to create an image then free it in the same procedure? What is the use of that?
If you create an image on the fly in a proc and in the same you save the image to disk, then maybe you don't need the image anymore so you free it.

If you are using a temp image in a proc to do some kind of processing on it and then copy the result to another image, than you can free the temp image.

Etc etc etc. millions of reasons.
WilliamL wrote: Is this going to cause a memory leak?
The PB manual says NO. It's easy to verify it, write a program creating images with the same number in a loop and check memory consumption.
"Have you tried turning it off and on again ?"
A little PureBasic review
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by Trond »

Code: Select all

CreateImage(123, 32, 32)
CreateImage(123, 32, 32) ; no leak

Image = CreateImage(#PB_Any, 32, 32)
CreateImage(Image, 32, 32) ; leak! (gives a debugger error)
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by WilliamL »

Isn't Trond's example interesting! You can create an image with #PB_Any but the value is to high to create another image with that number... (at least that was my debugger error) Well, the auto freeing of images (with fixed values) is shown to work.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by luis »

It's a warning, a BIG WARNING, but the image is created, anyway obviously the previous image created with #PB_Any is leaked.

The warning is due to:
help wrote: The static, indexed way, allows you to reference an object by a predefined numeric value. The first available index number is 0 and subsequent indexes are allocated sequentially. This means that if you use the number 0 and then the number 1000, 1001 indexes will be allocated and 999 (from 1 to 999) will be unused, which is not an efficient way to use indexed objects.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by luis »

Added (hopefully) support for the case discussed above by WilliamL, the use of numeric constants for PB objects and their automatic deallocation by PB when reusing the same number.

The updated example shows that.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: NoLeak - include to help you find memory leaks (UPDATED)

Post by skywalk »

Big Thanks to luis and trond for this post. 8)
Love it when code catches human error. :wink:
Maybe this feature could be added to the purifier as a sub option?
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply