Page 2 of 2

Posted: Thu May 14, 2009 5:06 pm
by DavidHart
I can post the back trace it it might be helpful
It's worth a try. Best to use a pastebin, and paste the relevant lines of source code too.
It seemed to be crashing very very early in the run.
Hmm. Do you create any static objects/functions? And what happens if you comment out the Connect() statement? Does it still crash?
I was asking if it is OK to post to an object which can not by itself handle the event.
No harm, but obviously not much good either.
The object I had in mind has NO event handler at all! Maybe it needs some sort of a handler for the event.Skip() to be used?
PushEventHandler adds a handler. You can then call Skip() inside that handler.
Have a good look at http://docs.wxwidgets.org/stable/wx_eve ... processing and http://docs.wxwidgets.org/stable/wx_eve ... lehandlers

Posted: Thu May 14, 2009 7:49 pm
by spamiam
DavidHart wrote:
I can post the back trace it it might be helpful
It's worth a try. Best to use a pastebin, and paste the relevant lines of source code too.
I will find out how to use a pastebin and then post the trace and code.
It seemed to be crashing very very early in the run.
Hmm. Do you create any static objects/functions? And what happens if you comment out the Connect() statement? Does it still crash?
No, everything works fine if I comment out the mainframe->Connect(...) statement. If I use the other type "Connect(wxID_ANY....) then it does not crash, and the one GraphicsWindow object to which the event was posted gets the event and is able to process it. The other instances do not get the event, despite all of them having the line event.Skip().
I was asking if it is OK to post to an object which can not by itself handle the event.
No harm, but obviously not much good either.
Not much good, but the idea was to get an event created SOMEWHERE so that I can later dynamically attach to it.
I will!

-Tony

Posted: Sat May 16, 2009 12:32 pm
by spamiam
I have done some more work with trying to trace down the source of the crash. It would appear to be a problem with the mainframe pointer. When I do the same connect to a different object, such as a scrollbar object, then the same command does not crash. See below:

Code: Select all

//
//File: GraphicsWindow.cpp
//

//GLOBAL OBJECTS WHICH CREATE EVENTS USED HERE
extern Analyzer *mainframe;
extern wxScrollBar* dataScroll;




//*********************************************************************
// class constructor

GraphicsWindow::GraphicsWindow(wxScrollBar* NAdataScroll, wxWindow* parent, 
                               wxWindowID id, const wxPoint& pos, const wxSize& size, 
                               long style, const wxString& name)
                              : wxScrolledWindow(parent, id, pos, size, style, name)
                        
{
     
//This Connection works.

    dataScroll->Connect(wxEVT_SCROLL_CHANGED, 
                    wxScrollEventHandler(GraphicsWindow::OnScroll), 
                    NULL, this);
 
//This connection does not cause a crash!                 
    dataScroll->Connect(DataReadyEvent,
                    CaptureEventHandler(GraphicsWindow::OnNewData),
                    NULL, this);
                    
//This connection with only the source pointer changed causes an instant crash!
    mainframe->Connect(DataReadyEvent,
                    CaptureEventHandler(GraphicsWindow::OnNewData),
                    NULL, this);

{....}
}

So It appears to be a problem with the mainframe pointer. Here is how both the dataScroll and mainframe pointers are defined and instantiated:

Code: Select all

//
//File:  AnalyzerMain.cpp
//

#include "AnalyzerMain.h"
#include "captureevent.h" //<-this contains the macro for  DataReadyEvent


//GLOBAL VARIABLES FOR EVENT PASSING
wxScrollBar     *dataScroll;
const wxEventType DataReadyEvent = wxNewEventType();


//*****************************************************
Analyzer::Analyzer(wxWindow *parent, wxWindowID id, const wxString &title,
                   const wxPoint &position, const wxSize& size, long style)
                 : wxFrame(parent, id, title, position, size, style)
{
     initVars();
     CreateGUIControls();
}




//*****************************************************
void Analyzer::CreateGUIControls()
{
     {...}

     dataScroll = new wxScrollBar(page1, wxID_ANY, wxPoint(0,0), wxSize(-1,-1),
                                  wxSB_HORIZONTAL, wxDefaultValidator,
                                  wxT("DATASCROLL"));
     dataScroll->Enable(true);
     dataScroll->SetRange(1<<16);
     dataScroll->SetThumbSize(1<<15);
     dataScroll->SetThumbPosition(1<<14);
     dataScroll->SetPageSize(dataScroll->GetPageSize()>>3);

     {....}
}
And here is where the mainframe object is declared and instantiated:

Code: Select all

//
//File:  AnalyzerApp.cpp
//

#include "AnalyzerApp.h"




//Create some GLOBAL variables which are event sources:
Analyzer *mainframe;



IMPLEMENT_APP(AnalyzerApp)

bool AnalyzerApp::OnInit()
{
    mainframe = new Analyzer(NULL);
    SetTopWindow(mainframe);
    mainframe->Show();
    return true;
}
As far as I can tell, the mainframe pointer should be a good one, and not pointing wildly when it is used in the GraphicsWindow code. It is not NULL when I check it in the GraphicsWindow when I print it out onto the graphics screen.

Any ideas about why the mainframe pointer whould cause a crash while the dataScroll does not?

-Tony

Posted: Sat May 16, 2009 1:30 pm
by doublemax
Any ideas about why the mainframe pointer whould cause a crash while the dataScroll does not?
quite obvious, the global variable "mainframe" is not initalized at that point in time.

Global variables are usually bad and in this particular case certainly not necessary.

If you don't want to change anything now, put a "mainframe=this;" at the first line into your Analyzer ctor.

Any you really should learn how to use a debugger, errors like this are easily detected in a debugger while looking at the code you can spend hours without seeing the mistake.

Posted: Sat May 16, 2009 5:45 pm
by spamiam
doublemax wrote:quite obvious, the global variable "mainframe" is not initalized at that point in time.
Well, You are correct, I did not initialize mainframe. I did not do this because I thought that the very first thing that happened when executing my applications code was to assign the mainframe variable (see the indicated statement)

Code: Select all

//This is the main application file.  It gets run as the very first thing

//Create some GLOBAL variables which are event sources:
Analyzer *mainframe;

IMPLEMENT_APP(AnalyzerApp)

bool AnalyzerApp::OnInit()
{
   mainframe = new Analyzer(NULL); //<-THIS IS THE ASSIGNNEMT, AND IT SEEMS TO BE DONE 
//                                 //BEFORE ANYTHING ELSE IN THE APPLICATION CODE

{....}
}
doublemax wrote:Global variables are usually bad and in this particular case certainly not necessary.
I agree, They are distasteful and no end of trouble. But Even more distasteful is having to pass the mainframe pointer when creating a child of a child of a child....

Is there another way to determine the mainframe pointer other than using a global or explicitly passing it to children?
doublemax wrote:If you don't want to change anything now, put a "mainframe=this;" at the first line into your Analyzer ctor.

I will try it. But I thought that mainframe would have been assigned that value by then
doublemax wrote:Any you really should learn how to use a debugger, errors like this are easily detected in a debugger while looking at the code you can spend hours without seeing the mistake.
You mean the the backtrace? Yes, it seems quite cryptic. I have looked at the backtrace, but I can not tell where it is trying to say that the crash occurred.

-Tony

EDIT:

P.S. I made the change you suggested to initialize mainframe to "this" in the Analyzer class in AnalyzerMain.coo. I then changed the variable name when instantiating the class in Anallyzer.App.cpp.

AND IT WORKED! All of it! Even the ability to catch the event even when it is posted to some other class. And ALL the instances of the GraphicsWindow class see the event. This achieves my goal! THANK YOU.

I still don't know why the statement
"mainframe = new Analyzer(...);"

is not equivalent to the statement
"mainframe = this;" when written inside the Analyzer class. I thought that the two pointers were equivalent.

-T

Posted: Sat May 16, 2009 6:51 pm
by DavidHart
You haven't shown where you create your GraphicsWindow instance, but I'd guess it's from either initVars() or CreateGUIControls().

These are called inside your Analyzer ctor, and the statement mainframe = new Analyzer(NULL) doesn't set mainframe until it returns.

Posted: Sat May 16, 2009 11:41 pm
by spamiam
DavidHart wrote:You haven't shown where you create your GraphicsWindow instance, but I'd guess it's from either initVars() or CreateGUIControls().

These are called inside your Analyzer ctor, and the statement mainframe = new Analyzer(NULL) doesn't set mainframe until it returns.
Yes, the GraphicsWindow(s) get created inside CreateGUI().
doesn't set mainframe until it returns.
AHHHHHHHHHHHHHHHHHH!, Of course. That explains it. Actually I did not know which came first, and not that you point it out, it makes sense that the assignment would be after the creation.

Thanks so much!

-Tony