addEventHandler allways crashes

elvman

27-11-2007 15:15:28

I am trying to add an eventHandler for my button, but it allways crashes on addEventHandler. The domes run fine, but I can't manage to implement this in my program. The code:
mSheet = gGUIManager->createSheet();
mLoginButton = mSheet->createButton();
mLoginButton->setDimensions(QuickGUI::Rect(200,320,100,20));
mLoginButton->setText("Log in");
mLoginButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&CLoginMenu::LogInButtonHandler,this);

I even tried to create button in the default sheet, but result was the same.
This is the call stack I get when debugging in Visual C++ 2005:
Client.exe!_free_dbg_nolock(void * pUserData=0x0dc14590, int nBlockUse=1) Line 1279 + 0x30 bytes C++
Client.exe!_free_dbg(void * pUserData=0x0dc14590, int nBlockUse=1) Line 1220 + 0xd bytes C++
Client.exe!operator delete(void * pUserData=0x0dc14590) Line 54 + 0x10 bytes C++
> Client.exe!std::allocator<QuickGUI::MemberFunctionSlot *>::deallocate(QuickGUI::MemberFunctionSlot * * _Ptr=0x0dc14590, unsigned int __formal=1) Line 141 + 0x9 bytes C++
Client.exe!std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >::_Insert_n(std::_Vector_iterator<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> > _Where=0xfdfdfdfd, unsigned int _Count=2, QuickGUI::MemberFunctionSlot * const & _Val=0x010c8080) Line 1160 C++
Client.exe!std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >::insert(std::_Vector_iterator<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> > _Where=0xfdfdfdfd, QuickGUI::MemberFunctionSlot * const & _Val=0x010c8080) Line 855 C++
Client.exe!std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >::push_back(QuickGUI::MemberFunctionSlot * const & _Val=0x010c8080) Line 800 + 0x2d bytes C++
Client.exe!QuickGUI::Widget::addEventHandler<lith::CLoginMenu>(QuickGUI::Widget::Event EVENT=EVENT_MOUSE_BUTTON_UP, void (const QuickGUI::EventArgs &)* function=0x0047801c, lith::CLoginMenu * obj=0x010c8028) Line 162 C++
Client.exe!lith::CLoginMenu::Init() Line 53 C++
Client.exe!lith::CApplication::Init() Line 107 + 0xb bytes C++
Client.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * __formal=0x00000000, char * strCmdLine=0x00151f4e, HINSTANCE__ * __formal=0x00000000) Line 56 + 0xb bytes C++
Client.exe!__tmainCRTStartup() Line 324 + 0x35 bytes C
Client.exe!WinMainCRTStartup() Line 196 C

kungfoomasta

27-11-2007 17:30:46

This is the same issue another user had. It looks like heap corruption to me, because you get a crash when it tries to "push_back" the event handler. As the call stack suggests, the iterator is invalid: _Where=0xfdfdfdfd

Can you confirm you can run the demo, and click the "Login" button, which displays text on the screen?

elvman

27-11-2007 18:17:15

Yes, as I said, the demo runs fine.

kungfoomasta

27-11-2007 18:21:25

That tells me somewhere in your code you are causing heap corruption. I can't really help in this area, unless I have access to your code, but even then that could take me a long time to analyze.

This might help:
http://www.ogre3d.org/wiki/index.php/Heap_Corruption

elvman

27-11-2007 18:40:42

Found out that the crash raises only in debug version of my program (release runs fine).

elvman

28-11-2007 13:23:17

I got the same crash when compiled and run the debug version of QuickGUIDemo.exe too.

kungfoomasta

28-11-2007 17:43:19

When you run the demo in debug, does it crash for the same reason? (what's the call stack say?)

I run the demo in release and debug all the time, and I've never had problems with std::vector::push_back...

elvman

28-11-2007 20:29:34

Ok, the demo crashed for some other reasons and now it works fine. But I can't get my application to work. Can you give me some clues, where to search for the bug?

As I said, my code looks like this:
mSheet = gGUIManager->createSheet();
mLoginButton = mSheet->createButton();
mLoginButton->setDimensions(QuickGUI::Rect(200,320,100,20));
mLoginButton->setText("Log in");
mLoginButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&CLoginMenu::LogInButtonHandler,this);

kungfoomasta

28-11-2007 21:47:29

The actual problem isn't related to QuickGUI at all, its because your code causes heap corruption. :(

Your code is manipulating memory that it isn't supposed to, which could be things like using dangling pointers, going out of bounds in an array, etc. How big is your application? If it's small, I could take a look, I guess... as long as we both understand QuickGUI is not the root cause for your crashing application. QuickGUI has only made this bug visible within your own code.

elvman

29-11-2007 00:02:23

Ok, made my project as short as possible. It does not have any global variables and has only 4 virtual functions (used correctly). There are no reasons for project to crash. Download here.

kungfoomasta

29-11-2007 00:08:53

First issue I see:

QuickGUI::registerScriptParser();

This needs to be called before resources have been initialized. In your case, you need to call this before the following line:

gRenderWindow=gRoot->initialise( true, "LitH");

Nothing else really pops out at me. I will have to try to run this in order to see if I can repro. Hopefully I will find some time to do this, your code is pretty small. You "Additional Include Directories" consist only of "..". Does this mean the project lies one level underneath your ogre include files? :?

elvman

29-11-2007 09:17:26

Does this mean the project lies one level underneath your ogre include files?
No, my project is pretty big and consists of 5 smaller projects. I have a Common folder, where common include and source files are placed (like md5 hash class etc.), these files are used by all projects, this has nothing to do with Ogre or other includes.

Calling QuickGUI::registerScriptParser(); before initialization of resources didn't help.

elvman

29-11-2007 15:40:03

Here I even made project shorter (by one class and a lot of functions and local/global variables and commented out namespaces), but it still crashes.

kungfoomasta

29-11-2007 17:37:54

I had to take a break last night, but hopefully this weekend I will fire up your stuff and see whats going on. I have a strange feeling that the code will work on my machine.. not sure what to make of that.

What version of Ogre are you using, what version of QuickGUI are you using, and what are your machine specs? OS, video card?

Thanks for your patience, I hope we find out whats going on.

elvman

29-11-2007 18:14:56

I use the latest version of Ogre (1.4.5) and the latest SVN revision of QuickGUI (267) + Microsoft Visual Studio Express 2005. I run it on my laptop - AMD Sempron 3300+, 768MB of RAM, ATI Mobility Radeon X200 with 128MB of memory (running on RAM).

hotdot

29-11-2007 21:45:59

your project is so small it even misses #include "Common/Definitions.h" :)

Please package all necessary file if you want us to help you :)

hotdot

29-11-2007 22:20:28

Kunfoomasta, the code crashes in the following :


in quickWidget.h

template<typename T> void addEventHandler(Event EVENT, void (T::*function)(const EventArgs&), T* obj)
{
mUserEventHandlers[EVENT].push_back(new MemberFunctionPointer<T>(function,obj));
}


when this code is called, wether because the initialisation sequence is not done well on something or because there is a bug :


QuickGUI::Sheet* mSheet = gGUIManager->createSheet();
QuickGUI::Button* mLoginButton = mSheet->createButton();
mLoginButton->setDimensions(QuickGUI::Rect(200,320,100,20));
mLoginButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&CApplication::LogInButtonHandler,this);


mUserEventHandlers is Initialized, but there is something fishy here, mainly because i think this code should use more defensive programming, we do not know if the object gets created correctly here and as soon as it is pushed into the vector, if it is considered as an object, a copy constructor gets called and some data could get lost if such as copy constructor is not found. I think in this cas what is pushed into the vector is actually a pointer since new returns a pointer, but in this case it actually looks like the software is trying to destruct the CApplication object, so i would return to the first hypothesis where the vector interpret this as an object because of a call to std::allocator<QuickGUI::MemberFunctionSlot *> then ::deallocate(QuickGUI::MemberFunctionSlot * * _Ptr=0x00e28f50, unsigned int __formal=1)'''std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *>

: see my stack trace :


ntdll.dll!7c901230()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7c96c943()
ntdll.dll!7c96cd80()
ntdll.dll!7c960af8()
Client.exe!std::_Destroy_range<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >(QuickGUI::MemberFunctionSlot * * _First=0x00e28f50, QuickGUI::MemberFunctionSlot * * _Last=0x0012f724, std::allocator<QuickGUI::MemberFunctionSlot *> & _Al={...}) Line 226 + 0x2e bytes C++
Client.exe!std::allocator<QuickGUI::MemberFunctionSlot *>::deallocate(QuickGUI::MemberFunctionSlot * * _Ptr=0x00e28f50, unsigned int __formal=1) Line 141 + 0x9 bytes C++
> Client.exe!std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >::_Insert_n(std::_Vector_iterator<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> > _Where=0xfdfdfdfd, unsigned int _Count=2, QuickGUI::MemberFunctionSlot * const & _Val=0x003b32e8) Line 1160 C++
Client.exe!std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >::insert(std::_Vector_iterator<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> > _Where=0xfdfdfdfd, QuickGUI::MemberFunctionSlot * const & _Val=0x003b32e8) Line 855 C++
Client.exe!std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> >::push_back(QuickGUI::MemberFunctionSlot * const & _Val=0x003b32e8) Line 800 + 0x2d bytes C++
Client.exe!QuickGUI::Widget::addEventHandler<CApplication>(QuickGUI::Widget::Event EVENT=EVENT_MOUSE_BUTTON_UP, void (const QuickGUI::EventArgs &)* function=0x00433356, CApplication * obj=0x003b3090) Line 162 C++
Client.exe!CApplication::Init() Line 141 C++
Client.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * __formal=0x00000000, char * strCmdLine=0x00151f33, HINSTANCE__ * __formal=0x00000000) Line 48 + 0x8 bytes C++
Client.exe!__tmainCRTStartup() Line 324 + 0x35 bytes C
Client.exe!WinMainCRTStartup() Line 196 C
kernel32.dll!7c816ff7()
msvcr80d.dll!_vcwprintf_p_l(const wchar_t * format=0x0022003d, localeinfo_struct * plocinfo=0x00380078, char * argptr=0x00220036) Line 1274 + 0x62 bytes C++



All in all i do not beleive in program corruption here, more that there is a chance there is a bug, maybe its because of compile settings ? anyhow hopes this gives a clue to the problem. KunfooMasta, be carefull and you should test MemberFunctionPointer, because when the destruction of this object get's called, there is a possibility the compiler will automatically delete non-pointer datamembers (though i did not checked if it was the case, or data members to delete)

Zini

29-11-2007 22:39:18


KunfooMasta, be carefull and you should test MemberFunctionPointer, because when the destruction of this object get's called, there is a possibility the compiler will automatically delete non-pointer datamembers (though i did not checked if it was the case, or data members to delete)


Sorry, but that is not correct. The crash can not possibly have to do anything with MemberFunctionPointer. If you look at the class, you will see, that its implementation is correct. Both the destructor and the (automatically generatored) copy-constructor work as they should.

Though I don't usually download complete projects to examine them, I made an exception with this one. And I can't find the cause for the crash in the source either.

I found a bug in QuickGUI's script parser, which can cause heap corruption. That might explain the crash. This is really only a blind guess, but it would be interesting to know, if elvman has changed the skinset script in any way.

hotdot

29-11-2007 22:46:38

hehe ok i was throwing things up, it also leaves me clueless :)

kungfoomasta

29-11-2007 22:52:31

It probably doesn't make any difference, but I can easily make a small change to remove any suspicions regarding the creation of the MemberFunctionPointer:

From:


template<typename T> void addEventHandler(Event EVENT, void (T::*function)(const EventArgs&), T* obj)
{
mUserEventHandlers[EVENT].push_back(new MemberFunctionPointer<T>(function,obj));
}


To:


template<typename T> void addEventHandler(Event EVENT, void (T::*function)(const EventArgs&), T* obj)
{
MemberFunctionSlot* newMemberFunctionSlot = new MemberFunctionPointer<T>(function,obj);
addEventHandler(EVENT,newMemberFunctionSlot);
}


This should tell us that the problem lies with the push_back function, (which is mind boggling) and isn't relevant to the creation of the memberFunctionPointer. Either way it will be more informative.

For completeness, I'll include the definition of the function addEventHandler(//2 args):

void Widget::addEventHandler(Event EVENT, MemberFunctionSlot* function)
{
mUserEventHandlers[EVENT].push_back(function);
}


Thanks to you both for looking into this and providing information. :)

hotdot

29-11-2007 23:05:32

trying this in a try/catch statement could help if any exceptions are raised, they would be catched me thinks

Zini

29-11-2007 23:06:59

I like the original version better (though that is mostly a matter of personal taste ;) ). Besides we already know that neither MemberFunctionPointer nor addEventHandler is the culprit (both are much to simple for a bug to hide in them).

Zini

29-11-2007 23:09:59


trying this in a try/catch statement could help if any exceptions are raised, they would be catched me thinks


Again, no! Exceptions aren't involved here and if they were, they would be handled properly. Actually some parts of QuickGUI aren't completely exception-safe, but that is only a minimal issue, which is not related in any way to the crash. A try-catch block won't change anything.

kungfoomasta

29-11-2007 23:14:33

hotdot, you're able to run his code and get this error, right? In the other test app you sent me code for, are you able to add Event Handlers without problem? Are you using VS2005 Express or studio? Maybe it's a Compiler/Project setting, as suggested earlier.

hotdot

29-11-2007 23:31:08

i am using visual studio professional, i think i have a trail on what to look for :

in vector.h

in the push_back function in :

this->_Alval.deallocate(_Myfirst, _Myend - _Myfirst); on line 1156, here is the visuals for this pointer :

- this [1](0x00e28f00) std::vector<QuickGUI::MemberFunctionSlot *,std::allocator<QuickGUI::MemberFunctionSlot *> > * const
- [0] 0x00e28f00 QuickGUI::MemberFunctionSlot *
- __vfptr 0x0087fde8 const QuickGUI::MemberFunctionPointer<class QuickGUI::Button>::`vftable' *
[0] 0x0076d8dd QuickGUI::MemberFunctionPointer<class QuickGUI::Button>::`scalar deleting destructor'(unsigned int) *
[1] 0x0076c3e8 QuickGUI::MemberFunctionPointer<class QuickGUI::Button>::execute(class QuickGUI::EventArgs const &) *


So it fails to deallocate those two. and frankly i have trouble seeing corruption on the horizon here. Could it be because the vector is trying to delete a const pointer ?

hotdot

29-11-2007 23:32:08

wait ill try it right now to add events in my stuff

hotdot

29-11-2007 23:36:05

mucho no problemo here captain :)

my app runs fine !

hotdot

29-11-2007 23:36:44

i have the version of your zip release though :)

kungfoomasta

29-11-2007 23:40:07

hotdot, I know you're set on thinking its not heap corruption, but it looks more and more like there is some corruption going on, basically trying to use memory that has been overwritten somehow. Is there any easy way to compare elvman's project settings vs yours? What happens if you copy in his QuickGUI code into your current setup, will it run?

hotdot

29-11-2007 23:49:50

Ok its heap corruption, ive stepped in my code versus his when the event is added, and the same events are present in the vector for the button and when the vector reallocates itselfs, something explode in his code that does not happen in mine, ill check the config now, brb in a few min.

hotdot

30-11-2007 00:03:34

first these pre-processor dir where missing : WIN32;_DEBUG;_WINDOWS (no effect after adding)

MultiThreaded debug instead of debug dll (no effects)

Incremental linking set to default i set it to yes ( no effect)

subsystem was not set.....no comment on this and i set it to \SUBSYSTEM:WINDOWS (still no effect)

On a side note, in DirectX it opens and close whitout saying a word, on the GL renderer it gives the error. As a final word on this i would say that there is something in his code initialization

I assembled some code place where there could be something fishy going on :)


F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(26): gRoot = new Ogre::Root("plugins.cfg","ogre.cfg","Ogre.log");
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(48): /*gInputManager = new InputManager();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(57): gGUIManager = new QuickGUI::GUIManager(vp);
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(78): gUserManager=new CUserManager();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(85): gGameManager=new CGameManager();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(93): gConsole=new CConsole();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(101): gLanguageManager=new CLanguageManager();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(109): gNetworkManager=new CNetworkManager();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(117): gLoginMenu=new CLoginMenu();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(125): /*ELVDELETED gServerMenu=new CServerMenu();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(132): gWorld=new CWorld();
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Application.cpp(319): mCurrentState->OnEnter(); //enter the new state
F:\ODD_DEV\GAMES\PC\COMMON\QUICKGUI\0_9_7\xxx\Main.cpp(46): gApplication=new CApplication();


I would say scrap this application, and restart from the ground up and follow the first tutorial on the wiki, check the example application as base, personaly i got two very different code base that uses QuickGUI and they do not give me that kind of trouble.

kungfoomasta

30-11-2007 00:12:10

Thanks a lot for looking into this hotdot.

Elvman, hopefully this information is helpful. I know its a pain, but if you could try making a new project, and copying in the QuickGUI Demo code, and let us know if that works, because the demo obviously runs without this problem on all our machines.

We probably shouldn't invest a whole lot more into this, there is a lot to do, and there isn't really anything further that we can do. It would be nice to see if another VS2005 express user could add event handlers without problem, but I don't know anybody off hand.

elvman

01-12-2007 18:02:52

The deadline for my project is coming really fast, so I don't have any time for searching for the error. I am forced to switch to CEGUI :(

Aquatix

01-12-2007 18:50:58

I am forced to switch to CEGUI
Well, have fun with CEGUI!

kungfoomasta

01-12-2007 19:41:33

Sorry for your troubles. :(

If I knew your problem, I would definately fix it immediately, but its just too ambiguous and machine and/or IDE dependent, I can't really analyze the problem or cause.