Unhandled exception: python.exe - Application Error

I tried to compile a debug version of wxPython to track this problem,
but didn't have much success compiling. So instead, I've pared my
application down to just the minimum code I need to crash
consistently and I'll append that to this e-mail. Sorry it's a
little long, but if I take out anything else, the crashes go away.
Perhaps someone out there with a debug version of wxPython could try
this and tell me why it is unhappy? Or perhaps I am just doing this
process wrong in general.

Here's what the application does:

The app has a main wxFrame which contains a single wxNotebook. The
wxNotebook is sized with a wxNotebookSizer. In the wxNotebook, I put
a wxPanel page and a variety of controls on that wxPanel. The
controls are organized with a mix of wxHORIZONTAL and wxVERTICAL
wxBoxSizer's. One of those controls is a wxButton (shortcut Alt-A)
which adds some more controls to the wxPanel. Because I will need to
remove arbitrary items as well as add more, I recreate and reassign
the wxBoxSizer's each time. Every ten times you add controls, the
application adds a page and begins again.

How to get the application to crash:

Run the application under Windows (I've got XP and haven't tried it
under any other O/S) and hold down Alt-A until you've added 35 or 45
items. Then close the application. I get a GAE every time I do
that.

wxPython is disposing of all the items automatically, so I don't
think I need to do anything differently there. I don't see an
alternative to recreating the sizers since I'll need to remove items
too. What am I doing wrong?

Thanks in advance!

Gre7g

Here's the code:

from wxPython.wx import *

class MainFrame(wxFrame):
    def __init__(self):
        wxFrame.__init__(self, parent=None)
        self.MainBook = wxNotebook(parent=self)
        Sizer = wxNotebookSizer(self.MainBook)
        self.SetSizer(Sizer)
        self.Items = []
        self.AddPage()
    def AddPage(self):
        self.Page = wxPanel(parent=self.MainBook)

        self.SpecialAttrText = wxStaticText(
            label='Special attributes', parent=self.Page)

        self.SpecialAttrLine = wxStaticLine(parent=self.Page)

        self.TrackRoot = wxCheckBox(label='Track _root',
            parent=self.Page, style=0)
        self.TrackRoot.SetValue(False)

        self.staticText3 = wxStaticText(label='Attribute:',
            parent=self.Page, style=0)
        self.staticText3.Enable(False)

        self.RootAttr = wxTextCtrl(parent=self.Page, style=0,
            value='_root')
        self.RootAttr.Enable(False)

        self.TrackParent = wxCheckBox(label='Track _parent',
            parent=self.Page, style=0)
        self.TrackParent.SetValue(False)

        self.TagAttrText = wxStaticText(label='Tag attributes',
            parent=self.Page)

        self.TagAttrLine = wxStaticLine(parent=self.Page)

        self.AddAttr = wxButton(label='&Add Attr.', parent=self.Page,
            style=0)
        EVT_BUTTON(self.AddAttr, self.AddAttr.GetId(), self.AddItem)

        self.TagChildrenText = wxStaticText(label='Tag children',
            parent=self.Page)

        self.TagChildrenLine = wxStaticLine(parent=self.Page)

        self.staticText8 = wxStaticText(
            label='Valid children definition:', parent=self.Page,
            style=0)

        self.ValidChildren = wxTextCtrl(parent=self.Page,
            size=wxSize(424, 40), style=wxTE_MULTILINE, value='')

        self.MainBook.AddPage(self.Page, str(len(self.Items)), True)
        self.Sizer()

    def Sizer(self):
        # Arrange stuff above sections
        Sizer1 = wxBoxSizer(wxVERTICAL)

        # Arrange special attribute items in top section
        Sizer2 = wxBoxSizer(wxHORIZONTAL)
        Sizer2.Add(self.SpecialAttrText, 0)
        Sizer2.Add(self.SpecialAttrLine, 1, wxLEFT | wxCENTER, 10)
        Sizer1.Add(Sizer2, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND,
            10)
        Sizer2 = wxBoxSizer(wxHORIZONTAL)
        Sizer2.Add(self.TrackRoot, 0, wxALIGN_CENTER)
        Sizer2.Add(self.staticText3, 0, wxALIGN_CENTER | wxLEFT, 10)
        Sizer2.Add(self.RootAttr, 0, wxALIGN_CENTER | wxLEFT, 10)
        Sizer2.Add(self.TrackParent, 0, wxALIGN_CENTER | wxLEFT, 30)
        Sizer1.Add(Sizer2, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND,
            10)

        # Arrange tag attribute items in middle section
        Sizer2 = wxBoxSizer(wxHORIZONTAL)
        Sizer2.Add(self.TagAttrText, 0)
        Sizer2.Add(self.TagAttrLine, 1, wxLEFT | wxCENTER, 10)
        Sizer1.Add(Sizer2, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND,
            10)
        for i in self.Items[(len(self.Items)-1) / 10 * 10:]:
            Sizer2 = wxBoxSizer(wxHORIZONTAL)
            Sizer2.Add(i[0], 0, wxALIGN_CENTER)
            Sizer2.Add(i[1], 0, wxLEFT, 10)
            Sizer1.Add(Sizer2, 0, wxTOP | wxLEFT, 10)
        Sizer1.Add(self.AddAttr, 0,
            wxLEFT | wxRIGHT | wxBOTTOM | wxALIGN_CENTER, 10)

        # Arrange child items in bottom section
        Sizer2 = wxBoxSizer(wxHORIZONTAL)
        Sizer2.Add(self.TagChildrenText, 0)
        Sizer2.Add(self.TagChildrenLine, 1, wxLEFT | wxCENTER, 10)
        Sizer1.Add(Sizer2, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND,
            10)
        Sizer2 = wxBoxSizer(wxHORIZONTAL)
        Sizer2.Add(self.staticText8, 0)
        Sizer2.Add(self.ValidChildren, 0,
            wxLEFT | wxBOTTOM | wxRIGHT, 10)
        Sizer1.Add(Sizer2, 0, wxLEFT, 10)

        self.Page.SetSizerAndFit(Sizer1)

    def AddItem(self, Event):
        if ((len(self.Items) % 10) == 0) and self.Items:
            self.AddPage()
        ST = wxStaticText(parent=self.Page,
            label=str(len(self.Items)))
        TE = wxTextCtrl(parent=self.Page,
            value=str(len(self.Items)))
        self.Items.append([ST, TE])
        self.Sizer()

class XMLApp(wxApp):
    def OnInit(self):
        wxInitAllImageHandlers()
        Main = MainFrame()
        self.SetTopWindow(Main)
        Main.Show()
        return True

App = XMLApp(0)
App.MainLoop()

Gre7g Luterman wrote:

Perhaps someone out there with a debug version of wxPython could try
this and tell me why it is unhappy?

Whenever I encounter the crashes on Windows, I then run on Linux,
get a core dump and use gdb. That always gives me an accurate
indication of where the problem is.

Roger

Gre7g Luterman wrote:

I tried to compile a debug version of wxPython to track this problem, but didn't have much success compiling. So instead, I've pared my application down to just the minimum code I need to crash consistently and I'll append that to this e-mail. Sorry it's a little long, but if I take out anything else, the crashes go away. Perhaps someone out there with a debug version of wxPython could try this and tell me why it is unhappy? Or perhaps I am just doing this process wrong in general.

Here's what the application does:

The app has a main wxFrame which contains a single wxNotebook. The wxNotebook is sized with a wxNotebookSizer. In the wxNotebook, I put a wxPanel page and a variety of controls on that wxPanel. The controls are organized with a mix of wxHORIZONTAL and wxVERTICAL wxBoxSizer's. One of those controls is a wxButton (shortcut Alt-A) which adds some more controls to the wxPanel. Because I will need to remove arbitrary items as well as add more, I recreate and reassign the wxBoxSizer's each time. Every ten times you add controls, the application adds a page and begins again.

How to get the application to crash:

Run the application under Windows (I've got XP and haven't tried it under any other O/S) and hold down Alt-A until you've added 35 or 45 items. Then close the application. I get a GAE every time I do that.

wxPython is disposing of all the items automatically, so I don't think I need to do anything differently there. I don't see an alternative to recreating the sizers since I'll need to remove items too. What am I doing wrong?

I havn't been able to track down the causae of the problem yet, but there is no real reason to recreate the sizer each time you add something. Just keep a reference to the sizer you need to add something to and Add or Insert the item as needed. For removing you can use sizer.Detach, or if it's a window item then just destroying the child window will cause it to remove itself from the sizer.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!