if you watch memory usage it slowly climbs upwards, whereas if you use
a button (uncomment line 126) instead of the custom widget, memory
usage stays stable.
also if you let the example run long enough, the window eventually
stops drawing properly (about 2000 refresh cycles on my machine, not
sure if this is a consistent number)
i think this may be related to an odd crash i'm experiencing with an
app I am writing where there is a lot of this sort of UI destruction
and rebuilding happening.
The wx.PyFoo classes need to hold some additional references in order to be able to reflect the virtual method calls to Python... I'll check if maybe some of those are not being cleaned up properly.
···
On 12/10/09 5:42 PM, macaronikazoo wrote:
I think the below script demonstrates a memory leak somewhere when
using custom widgets in wxpython.
if you watch memory usage it slowly climbs upwards, whereas if you use
a button (uncomment line 126) instead of the custom widget, memory
usage stays stable.
also if you let the example run long enough, the window eventually
stops drawing properly (about 2000 refresh cycles on my machine, not
sure if this is a consistent number)
i think this may be related to an odd crash i'm experiencing with an
app I am writing where there is a lot of this sort of UI destruction
and rebuilding happening.
so in this particular case I actually solved teh memory leak problem
by adding the following method to the MenuCtrl class:
def __del__( self ):
self._menu.Destroy()
but I'm unsure why I need to destroy that menu like this. how come it
doesn't get garbage collected when its container object is destroyed?
there are no other references to it - in python at least.
I think I have another similar problem where timer objects aren't
being garbage collected either. do menu's and timers get implicitly
held on to by frame objects or something? after all, they don't have
"parent's" per-se.
or perhaps it is that because the wx.Menu has a python referrer it
doesn't get destroyed which causes the python object to not get gc'd?
i don't really understand how to debug these interactions.
because i experience the same problem with timers. if i have a python
object holding a reference to a timer I get memory leaks as well -
presumably for the same reason.
-h.
so in this particular case I actually solved teh memory leak problem
by adding the following method to the MenuCtrl class:
def __del__( self ):
self._menu.Destroy()
Ah, I didn't see that you were creating a menu there. I was focusing on the fact that you were using a wx.PyControl and didn't look at the rest of it.
but I'm unsure why I need to destroy that menu like this. how come it
doesn't get garbage collected when its container object is destroyed?
there are no other references to it - in python at least.
This is partially due to historical reasons, and partly due to how object ownership is handled on the C++ side. Since menus are almost always on other menus or a menubar, and it could be considered that the parent menu/menubar owns the menu, I made it such that the Python proxy object does not own the C++ menu object (way back in the early days of wxPython,) so if you use a menu by itself you have to explicitly destroy it when done. Since it's a C++ object then the Python garbage collector is not aware of it.
This is similar to how child windows are owned by their parent, but if you want to make them go away before the parent does then you need to explicitly destroy them too.
I think I have another similar problem where timer objects aren't
being garbage collected either. do menu's and timers get implicitly
held on to by frame objects or something? after all, they don't have
"parent's" per-se.
Depending on how it's used a timer can hold a reference to itself (actually the C++ object holds a reference to the Python proxy object) while it's running. So usually it's sufficient to just explicitly stop the timer when the window it's sending events to is closed. Normal reference counting in the proxy should then take care of destroying the C++ object in this case.