Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => Topic started by: ollydbg on January 31, 2019, 07:50:08 am

Title: wxsmith assert on wxMathplot control (wxPen::GetWidth)
Post by: ollydbg on January 31, 2019, 07:50:08 am
I have a CodeBlocks project, which has a wxMathPlot control(gui designer is wxSmith). It is designed under Official C::B 17.12. Now, I open the wxs file with the latest C::B trunk build against wx3.1.2, C::B just hangs.

I just run the C::B under GDB, and see such assert error:
Code
[debug]> bt 30
[debug]#0  0x66488871 in wxDefaultAssertHandler(wxString const&, int, wxString const&, wxString const&, wxString const&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#1  0x66487bad in wxOnAssert(char const*, int, char const*, char const*, wchar_t const*) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#2  0x666b0e07 in wxPen::GetWidth() const () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#3  0x17f5312d in mpFXY::Plot (this=0x20d73140, dc=..., w=...) at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\contrib\wxContribItems\wxmathplot\mathplot.cpp:535
[debug]#4  0x17f58d94 in mpWindow::OnPaint (this=0x20d6bfe8) at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\contrib\wxContribItems\wxmathplot\mathplot.cpp:1805
[debug]#5  0x66482d92 in wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#6  0x66483267 in wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#7  0x665d9bde in wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#8  0x665d9d2a in wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#9  0x665da431 in wxEvtHandler::TryHereOnly(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#10 0x665da49a in wxEvtHandler::ProcessEventLocally(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#11 0x665da4f3 in wxEvtHandler::ProcessEvent(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#12 0x665dc1c2 in wxEvtHandler::SafelyProcessEvent(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#13 0x666dc741 in wxWindow::HandlePaint() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#14 0x666de1ff in wxWindow::MSWHandleMessage(long*, unsigned int, unsigned int, long) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#15 0x666ce4f0 in wxWindow::MSWWindowProc(unsigned int, unsigned int, long) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#16 0x666d6292 in wxWndProc(HWND__*, unsigned int, unsigned int, long)@16 () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#17 0x764862fa in gapfnScSendMessage () from C:\windows\syswow64\user32.dll
[debug]#18 0x000208ea in ?? ()
[debug]#19 0x76487316 in USER32!GetDC () from C:\windows\syswow64\user32.dll
[debug]#20 0x666d6220 in wxWindow::SubclassWin(HWND__*) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#21 0x76486de8 in USER32!GetThreadDesktop () from C:\windows\syswow64\user32.dll
[debug]#22 0x00000000 in ?? ()
[debug]>>>>>>cb_gdb:
[debug]> frame 3
[debug]#3  0x17f5312d in mpFXY::Plot (this=0x20d73140, dc=..., w=...) at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\contrib\wxContribItems\wxmathplot\mathplot.cpp:535
[debug]D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\contrib\wxContribItems\wxmathplot\mathplot.cpp:535:17506:beg:0x17f5312d
[debug]>>>>>>cb_gdb:

The source code of the assert is in the line (m_pen.GetWidth())
Code
void mpFXY::Plot(wxDC & dc, mpWindow & w)
{
    if (m_visible) {
        dc.SetPen( m_pen);

        double x, y;
        // Do this to reset the counters to evaluate bounding box for label positioning
        Rewind(); GetNextXY(x, y);
        maxDrawX = x; minDrawX = x; maxDrawY = y; minDrawY = y;
        //drawnPoints = 0;
        Rewind();

        wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
        wxCoord endPx   = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
        wxCoord minYpx  = m_drawOutsideMargins ? 0 : w.GetMarginTop();
        wxCoord maxYpx  = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();

        wxCoord ix = 0, iy = 0;

        if (!m_continuous)
        {
            // for some reason DrawPoint does not use the current pen,
            // so we use DrawLine for fat pens
            if (m_pen.GetWidth() <= 1)//*****************************crash here
            {
                while (GetNextXY(x, y))
                {
                    ix = w.x2p(x);
                    iy = w.y2p(y);
                    if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx))) {
                        dc.DrawPoint(ix, iy);
                        UpdateViewBoundary(ix, iy);
                    };
                }
            }
            else
            {
                while (GetNextXY(x, y))
                {
                    ix = w.x2p(x);
                    iy = w.y2p(y);
                    if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx))) {
                        dc.DrawLine(ix, iy, ix, iy);
                        UpdateViewBoundary(ix, iy);
                    }
    //                dc.DrawLine(cx, cy, cx, cy);
                }
            }
        }

Any one has ideas how this happens? A wrong wxPen? or an empty wxPen?
Because it crash here: https://github.com/wxWidgets/wxWidgets/blob/master/src/msw/pen.cpp
Code
int wxPen::GetWidth() const
{
    wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );

    return M_PENDATA->GetWidth();
}
Title: Re: wxsmith assert on wxMathplot control (wxPen::GetWidth)
Post by: ollydbg on January 31, 2019, 09:23:45 am
From the document, I see:
Quote
virtual bool wxPen::IsOk    (       )    const
   virtual

Returns true if the pen is initialised.

Notice that an uninitialized pen object can't be queried for any pen properties and all calls to the accessor methods on it will result in an assert failure.


When looking at the source code of: src\plugins\contrib\wxContribItems\wxmathplot\mathplot.cpp
I see that the member variable m_pen don't have a specific constructor, so maybe the default constructor is used, but, the document said:

Quote
wxPen::wxPen    (       )    

Default constructor.

The pen will be uninitialised, and IsOk() will return false.


I don't have an idea on how to solve such issue.
Maybe, we have to add the IsOk check on every m_pen function call?

EDIT:
Oh, the wxPen has correctly initialized, see below:
Code
mpLayer::mpLayer() : m_type(mpLAYER_UNDEF)
{
    SetPen((wxPen&) *wxBLACK_PEN);
    SetFont((wxFont&) *wxNORMAL_FONT);
    m_continuous = FALSE; // Default
    m_showName   = TRUE;  // Default
    m_drawOutsideMargins = TRUE;
    m_visible = true;
}

Title: Re: wxsmiith assert on wxMathplot control (wxPen::GetWidth)
Post by: Miguel Gimenez on January 31, 2019, 09:41:38 am
I have just tested one of my applications using mathplot with wx312 and works fine. It uses default pens and one custom pen, all work.

Are you using the default pen from mpLayer constructor or have you changed it using SetPen() from your code?. May be this call uses a malformed pen.
Title: Re: wxsmith assert on wxMathplot control (wxPen::GetWidth)
Post by: ollydbg on January 31, 2019, 04:05:23 pm
I have just tested one of my applications using mathplot with wx312 and works fine. It uses default pens and one custom pen, all work.

Are you using the default pen from mpLayer constructor or have you changed it using SetPen() from your code?. May be this call uses a malformed pen.

Hi, thanks for the help. Now, I can reproduce the crash issue by a minimal C::B project created by C::B 17.12. See attachment, you don't need to build the project, just try to open the cbp file under C::B trunk, and try to "review the GUI" under wxsmith.
Title: Re: wxsmiith assert on wxMathplot control (wxPen::GetWidth)
Post by: Miguel Gimenez on January 31, 2019, 05:10:43 pm
Got it. In line 254 of wxsVector.cpp we have

Code
wxPen   pen;

This leaves pen uninitialized. Later, if you define a colour for the vector the pen gets initialized (line 283) and all is fine, but if you don't then the pen is left as is and SetPen() is called (line 284) with the uninitialized pen.

You can see in your wxs file that VECTOR1 has a colour defined but VECTOR2 not.

Patch is attached
Title: Re: wxsmiith assert on wxMathplot control (wxPen::GetWidth)
Post by: BlueHazzard on January 31, 2019, 11:50:27 pm
So this should be fixed in the wxSmith code?
ollydbg are you fixing this? Should we create a ticket so it won't get lost?
Title: Re: wxsmith assert on wxMathplot control (wxPen::GetWidth)
Post by: ollydbg on February 01, 2019, 01:50:50 am
So this should be fixed in the wxSmith code?
ollydbg are you fixing this? Should we create a ticket so it won't get lost?
I will create a ticket if it can not be fixed in one week.
I think we have to fix the code in wxsmith.

@Miguel Gimenez
many many thanks, you find the true reason. I will test your patch asap.

Sent from my phone.

Title: Re: wxsmiith assert on wxMathplot control (wxPen::GetWidth)
Post by: ollydbg on February 01, 2019, 03:00:41 pm
This crash issue is fixed in trunk now. Thanks!