Hi,
Hi,
As a newcomer (coming from PyGTK), I've been alarmed by the number of
segmentation faults that I've experienced using wxPython. These are the
only such problems that I have ever experienced using Python and based on
the workarounds I have used to dodge them (and the use of names such as
Destroy() for object methods) I have developed a theory as to what's
causing
them.
I suspect that some of these Destroy() methods end up invoking memory
release within the C++ code. This can cause problems in Python in (at
least) two ways:
The Destroy() method has its own niche applications for non-toplevel
windows, i.e. you do not use it all the time for all the widgets: if
you Destroy() a wx.Frame (for example when you close a window) all its
children are automatically destroyed for you.
That's where it's most dangerous.
I see it as "useful", and not particularly dangerous: I have never
seen a segmentation fault report because a wx.Frame destroyed its
children while closing.
You've been lucky. It is not a good idea to be releasing memory manually in an automatic memory management. That's why Python doesn't have ANY way of doing it normally.
Programmer managed memory allocation/release is error prone and difficult and therefore bad. Automatic memory management with a good garbage collector is good. Mixing the two is very bad.
Another way of looking at this is to say don't use C++/Java programming paradigms when programming in Python - they're different languages and require different methodologies. I realize the wxPython is wrapper for a C++ library and that it's not possible to completely avoid C++ey things but they should be kept to a minimum.
1. there are still (active) references to the released memory and if
these
references are accessed a segmentation fault will result, and
2. Python's garbage collector doesn't notice that the memory has been
released and tries to release it itself when it notices that the object
is
no longer accessible (i.e. normal procedure) resulting in a segmentation
fault.
I have very little experience with Linux so I can't really comment on
these statements. You will probably have to show some minimal,
standalone sample application that demonstrates the problem.
See my other reply on this thread.
I haven't used 2.8 since a veeeeery long time (2.9 is way much better
than 2.8 overall),
Unfortunately, the documentation on wxpython's site is still for 2.8 so newcomers such as myself expect the behaviour to match that. Also, as 2.9 its labelled (probably unjustly) "unstable" most distributions ship 2.8. Maybe they should be encouraged to ship 2.9?
But, more to my point, you will find if you look into it that 2.9 and also 2.8 have undergone piecemeal changes similar to what I propose in order to fix segmentation fault bugs. So what I'm really proposing is a cessation of piecemeal changes and a systematic shift to an "automatic only" memory management model.
but a couple of comments anyway:
- Allowing the users to rely on wx.Sizer.Remove to destroy its managed
windows was a big mistake, in my opinion: wx.Sizer is not a sub-class
of wx.Window and it cannot have any parent-child relationship with any
wxPython control. I am happy this behaviour has been removed in 2.9;
No argument from me BUT it was removed to avoid segmentation faults. So it wasn't just a philosophical error it was a fundamental programming error.
BTW I think it would make programmers' lives easier if it did Hide() on the removed object to save the programmer the need to do it himself (btw Python won't automatically destroy/release the window while its still visible (in the Show(True) sense)). However, because it is possible that the programmer does want the window to be still visible after it is removed we are left with the problem of how to allow that.
So I would suggest changing the interface to Remove() to be
def Remove(self, child, hide=True):
this would allow programmers who didn't the window to be hidden after removal to achieve their aim.
- The issues with UltimateListCtrl (or any other AGW widget) should
not be blamed on the library behaviour, but on the sloppy programmer
who created them (me, in this case). In general, however, when you
have an issue with a custom control (i.e., everything in wx.lib and
its sub-directories), you should do the following:
No, the fault is wxPython's as the Destroy() method should NOT release the memory but just do any other housekeeping that's necessary such as removing it from any internal widget management structures.
BTW I emailed the address in the AGW documentation a bug report about this issue and followed up with a email about the workaround I used which was to redefine my embedded windows Destroy() method to be Show(False). Did you receive these.
1) Get the latest SVN version of the problematic widget (as they can
evolve much faster than wxPython does over time);
I'm not so wrapped in wxPython that I want to use other than the latest version in the Linux distribution that I'm using (at this stage).
But I do look in the bug system to see if my problem has been reported/fixed and if not I report it.
I then develop a workaround which I document with a # WORKAROUND comment that shows up in my editors "TO DO" list so that I'm prompted to revisit them when Fedora update wxPython.
2) Test again.
Of course.
Most of them are wxPython-version-independent (to an extent), so they
can be used with 2.8 and 2.9 without modification. If the issue
persists, file a ticket to the wxTrac:
http://trac.wxwidgets.org/
I've done this (see #14642) and I started this thread in response to a request made in the discussion of that bug report.
Specifying the component (AGW in this case).
OK. I didn't realize AGW bugs went here as well which is why I emailed my bug report to the email address in the documentation.
I think that the only long term solution to this problem is to stop
invoking
C++ functions that release memory (at least for memory that Python knows
about) and trust the Python garbage collector to do its job.
In short, using two competing memory management mechanisms at the same
time
is asking for trouble. There are no explicit memory management functions
in
Python for this reason.
Cheers
Peter
PS For the convenience of programmers, using a obj.Show(False) as a
substitute for obj.Destroy() would have the desired effect from a user
perspective.
From a user perspective it may be doing what you think, but calling
obj.Show(False) simply hides the widget: it is still there, it's
occupying GDI objects (which on Windows can become a scarce resource)
and it can sometimes mess your your interface anyway.
Only while there is a variable or object field referencing it. As soon as
there are none then the Python garbage collector will dispose of it and it
should be stressed that this is the only time that it can be safely
disposed.
There is nothing you or I can do about this because this approach will
probably require a big rewrite of the underlying logic of the SWIG
wrappers.
If they are well compartmentalised it should not be a big change. The alternative is to get there by stealth as people trigger segmentation faults and you have fix them.
As long as a widget has been created and it is sitting in a
frame, no Python garbage collector will be able to remove it from
there, whatever the variable referring to it in your code is doing: it
can go out of scope, it can be deleted, it doesn't matter. The widget
will still be there.
I'm not sure what you mean. But the fact that the segmentation faults tend to be triggered when Python's garbage collector tries to release the memory after it has already been released by the Destroy() seems to belie your argument.
Peter
PS I suspect that the fix may be as simple as modifying the way that the Destroy() methods in wxWidgets are mapped to wxPython. Probably only the one that is defined in the widget at the bottom of the hierarchy (with any luck).
···
On 09/18/2012 03:23 PM, Andrea Gavana wrote:
On 18 September 2012 01:34, Peter Williams wrote:
On 09/17/2012 09:35 PM, Andrea Gavana wrote:
On 16 September 2012 07:32, Peter Williams wrote: