Memory leak image menu?

Mac OSX specific forum
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Memory leak image menu?

Post by Rinzwind »

Code: Select all

EnableExplicit

Global NewList IconList(), menu, e

Procedure CreateImg()
  Protected img
  img = CreateImage(#PB_Any, 24, 24, 32)
  StartDrawing(ImageOutput(img))
  Box(0, 0, 24, 24, RGB(Random(255), Random(255), Random(255)))
  StopDrawing()
  ProcedureReturn img
EndProcedure


Procedure NewMenu()
  Protected c, i, img
  If menu
    FreeMenu(menu)
  EndIf
  ClearList(IconList())
  menu = CreateImageMenu(#PB_Any, WindowID(0))
  MenuTitle("Test")
  c = 64
  For i = 0 To c
    img = CreateImg()
    AddElement(IconList())
    IconList() = img
    MenuItem(#PB_Any, "" + img, ImageID(img))
  Next
EndProcedure

Procedure RetainCounts()
  Protected img
  ForEach IconList()
    img = IconList()
    Debug "" + img + ", " + CocoaMessage(0, ImageID(img), "retainCount")
  Next    
EndProcedure


OpenWindow(0, 0, 0, 400, 300, "Test")
ButtonGadget(1, 10, 10, 120, 30, "Create Menu")
ButtonGadget(2, 10, 50, 120, 30, "Retain Count")
ButtonGadget(3, 10, 90, 120, 30, "Free Menu")

Repeat
  e = WaitWindowEvent()
  Select e
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          NewMenu()
        Case 2
          RetainCounts()
        Case 3
          ForEach IconList()
;             While CocoaMessage(0, IconList(), "retainCount")  > 1
;               CocoaMessage(0, IconList(), "release")
;             Wend
          Next
          If menu
            FreeMenu(menu)
            menu = 0
          EndIf
      EndSelect
  EndSelect
      
Until e = #PB_Event_CloseWindow


Click Create Menu
Click Retain Counts
Open/show/click menu
Click Retain Counts
Free Menu
Click Retain Counts

The images are still in memory after menu is freed? I would expect a crash because the object should not be there anymore...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Memory leak image menu?

Post by wilbert »

You have to free an image created with CreateImage yourself using FreeImage.
Windows (x64)
Raspberry Pi OS (Arm64)
Fred
Administrator
Administrator
Posts: 16664
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Memory leak image menu?

Post by Fred »

Yes it's your responsibility to clear the original images.
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Memory leak image menu?

Post by Rinzwind »

Ok, I asked because of this different example below and tried to duplicate it using normal PB images but failed to notice the freeimage stuff...

Below uses existing NSImage, uses it for menu.How to free it? retainCount still has a value after the menu is long gone.

Code: Select all

EnableExplicit

Global NewList IconList(), m, e

Procedure NewMenu()
  Protected icon, icon2, i, img, c = 64
  If m
    FreeMenu(m)
    
  EndIf
  ClearList(IconList())
  m = CreateImageMenu(#PB_Any, WindowID(0))
  MenuTitle("Test")
  ;Protected pool = CocoaMessage(0, 0, "NSAutoreleasePool new")
  For i = 1 To c
    If icon = 0
      icon = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "iconForFileType:$", @"txt")
      AddElement(IconList())
      IconList() = icon
    EndIf
    ;Debug "A " + icon + ", " + CocoaMessage(0, icon, "retainCount")
    MenuItem(#PB_Any, "" + i + " " + icon, icon)
    ;Debug "B " + icon + ", " + CocoaMessage(0, icon, "retainCount")
  Next
EndProcedure

Procedure ReleaseCounts()
  Protected icon
  ForEach IconList()
    icon = IconList()
    Debug "" + icon + ", " + CocoaMessage(0, icon, "retainCount")
  Next    
EndProcedure

OpenWindow(0, 0, 0, 400, 300, "Test")
ButtonGadget(1, 10, 10, 60, 30, "CMenu")
ButtonGadget(2, 10, 50, 60, 30, "RCount")
ButtonGadget(3, 10, 90, 60, 30, "FMenu")

Repeat
  e = WaitWindowEvent()
  Select e
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          NewMenu()
        Case 2
          ReleaseCounts()
        Case 3
          FreeMenu(#PB_All)
          m = 0
      EndSelect
  EndSelect
      
Until e = #PB_Event_CloseWindow

Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Memory leak image menu?

Post by Rinzwind »

Steps:

CMenu
RCount -> 64
FMenu
Wait few secs
RCount -> crash (expected)

Exit, run again
CMenu
RCount -> 64
Open the menu
RCount -> 192
FMenu
Wait few secs
RCount -> still 128

I don't know how to reliable cleanup...
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Memory leak image menu?

Post by Rinzwind »

Btw also with the original PB image code it seems memory is leaked. Activity monitor shows memory increase every time one presses create menu, open the menu, free menu with this code, easily can get is passed 100 MB by just keep clicking. When one does NOT open/click the menu, NO memory increase is seen:

Code: Select all

EnableExplicit

Global NewList IconList(), menu, e

Procedure CreateImg()
  Protected img
  img = CreateImage(#PB_Any, 128, 128, 32)
  StartDrawing(ImageOutput(img))
  Box(0, 0, 128, 128, RGB(Random(255), Random(255), Random(255)))
  StopDrawing()
  ProcedureReturn img
EndProcedure


Procedure NewMenu()
  Protected c, i, img
  If menu
    FreeMenu(menu)
  EndIf
  ClearList(IconList())
  menu = CreateImageMenu(#PB_Any, WindowID(0))
  MenuTitle("Test")
  c = 128
  For i = 0 To c
    img = CreateImg()
    AddElement(IconList())
    IconList() = img
    MenuItem(#PB_Any, "" + img, ImageID(img))
  Next
EndProcedure

Procedure RetainCounts()
  Protected img
  ForEach IconList()
    img = IconList()
    Debug "" + img + ", " + CocoaMessage(0, ImageID(img), "retainCount")
  Next   
EndProcedure


OpenWindow(0, 0, 0, 400, 300, "Test")
ButtonGadget(1, 10, 10, 120, 30, "Create Menu")
ButtonGadget(2, 10, 50, 120, 30, "Retain Count")
ButtonGadget(3, 10, 90, 120, 30, "Free Menu")

Repeat
  e = WaitWindowEvent()
  Select e
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          NewMenu()
        Case 2
          RetainCounts()
        Case 3
          ForEach IconList()
;             While CocoaMessage(0, IconList(), "retainCount")  > 1
;               CocoaMessage(0, IconList(), "release")
;             Wend
          Next
          If menu
            FreeMenu(menu)
            ForEach IconList()
              FreeImage(IconList())
            Next
            menu = 0
          EndIf
      EndSelect
  EndSelect
     
Until e = #PB_Event_CloseWindow
Fred
Administrator
Administrator
Posts: 16664
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Memory leak image menu?

Post by Fred »

Moved again for investigation
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Memory leak image menu?

Post by Rinzwind »

Progress? Kind of waiting for a fix. Hope it gets some attention.
Fred
Administrator
Administrator
Posts: 16664
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Memory leak image menu?

Post by Fred »

It's a stange bug, because if we don't click on the menu, everything is fine. I we display it, the retainCount goes up to 4 which is not expected. Could be an OS X bug because usually menu are not freeed/changed at runtime.
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Memory leak image menu?

Post by Rinzwind »

I kind of have no other option because PB doesnt let me change menus dynamically (feature request ;))
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Memory leak image menu?

Post by wilbert »

It looks indeed like a macOS issue.

@Rinzwind, can't you reuse the images instead of creating new ones ?
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply