QxtGlobalShortcut causes SIGSEGV in console application - c++

I am writing a console application that allows you to use ECMAScript to move the mouse about, and define hot keys etc. The mouse stuff works, and now I am trying to add in the ability to define hot keys that when pressed will call a QtScript handler function.
The problem is, when I try to use QxtGlobalShortcut to create the hot key, I get a SIGSEGV and everything crashes.
Here is the code:
int Keyboard::hot_key(QString key) {
QxtGlobalShortcut shortcut;
shortcut.setShortcut(QKeySequence(key));
shortcut.setEnabled(true);
connect(&shortcut, SIGNAL(activated()), this, SLOT(hot_key_pressed()));
return 0;
}
This line QxtGlobalShortcut shortcut;, if I gut the entire function except for that line, it still throws a seg fault.
And the debugger says:
1 ZNK17QxtGlobalShortcut8shortcutEv C:\Qxt\lib\QxtGui.dll 0 0x6f6f14a6
2 ZN17QxtGlobalShortcutC1EP7QObject C:\Qxt\lib\QxtGui.dll 0 0x6f6f14f7
3 Keyboard::hot_key keyboard.cpp 16 0x403c0c
4 Keyboard::qt_metacall moc_keyboard.cpp 74 0x404740
5 QMetaObject::metacall qmetaobject.cpp 237 0x8f5ff8
Considering how not so easy, in my opinion, Windows hotkeys are, I'd really like to use Qxt, but so far I am just hitting a wall. If anyone could point me in the right direction, or even recommend some other library that might be able to help me, or a tutorial on hotkeys that would be awesome.
Thanks in advance!

Your shortcut object is constructed on the stack. It will get deleted as soon you leave that function, so your code is bound to fail even if it did not die in that function.
You should be creating that object with:
QxtGlobalShortcut *shortcut = new QxtGlobalShortcut;
If you care about not leaking that, store that pointer as a member of your class and delete it in it's destructor.
As for the crash, that could happen if you are using a version of Qxt older than 6.0 and haven't initialized a QxtApplication yet.

Related

Change image on StaticBitmap wxWidgets

I would like to have a window, in which a picture changes depending on what is happening during an infinite loop.
Imagine someone walking around and when he leaves a given track, the program should display an arrow towards the direction of the track. Therefore I have a program, which determines the distance between user and track, but I have no idea on how to update the image.
I use code::blocks with wxWidgets and think I have to use the wxStaticBitmap class. (If there is a better way, please tell me.)
I tried with:
while(true)
{
updatePosition();
if(userNotOnTrack)
{
if(trackRightOfUser)
{
StaticDirectionBitmap->SetBitmap("D:\\WindowsDgps\\WindowsDgpsGraphic\\arrow_right.png");
}
}
}
(Note that this snippet is mostly pseudocode, except the StaticDirectionBitmap part.)
On default the Bitmap has a "no_arrow" image. With this I get an error: error: no matching function for call to 'wxStaticBitmap::SetBitmap(const char [51])'|. I see from the documentation that this cannot work, but I have no idea what could.
If anyone knows how to handle this, I would be happy to hear. I remember a few years back, when I tried something similar in C# and failed completely because of thread safety... I hope it is not this hard in C++ with wxWidgets.
SetBitmap takes a wxBitmap parameter not a string. So the call should look something like:
SetBitmap(wxBitmap( "D:\\WindowsDgps\\WindowsDgpsGraphic\\arrow_right.png", wxBITMAP_TYPE_PNG) );
Make sure prior to making this call that the png handler has been added with a call like one of the following:
wxImage::AddHandler(new wxPNGHandler);
or
::wxInitAllImageHandlers();
The easiest place to do this is in the applications OnInit() method.
If you want update the static bitmap from a worker thread, you should throw a wxThreadEvent and then make the call to SetBitmap in the event handler. The sample here shows how to generate and handle these events.

What could be the cause for runtime "can't find linker symbol for virtual table..." error in Qt?

This question was asked in similar ways multiple times, for example at stackoverflow or forum.qt.io or qtcentre.org. The problem is that this error message is so vague that one solution cannot be applied to another scenario. Most of the threads are dead in the middle of the discussion though :-(
So the complete error message that I get in my Qt application is:
can't find linker symbol for virtual table for "OneOfMyClasses" value
found "QString::shared_null" instead
The OneOfMyClasses changes depending on various things, the QString::shared_null stays the same for all errors that I get. Here is a screenshot of my logging console:
Why is the font color pink, so who is printing this message?
Why do I only see this message when I set a breakpoint and step through my code? This message does not appear when simply running the application.
The point where it happens is in this function in the source line right before the current position (yellow arrow):
So according to the message I stepped into m_pStateWidget->insertNavLabel(...) and the error message is printed somewhere in the constructors inside Qt related to the QString class. So I tried the following, which moves the problem away from this code location:
When doing this I get the same error message a few code lines below with another class name in the message, note that the QString::shared_null stays the same.
It appears to me that I have some sort of corrupted memory.
How should I start investigating this issue? I'm afraid to change the code because this might hide the problem as described above.
What's up with the QString::shared_null? I have found that others often see the same in their error messages.
Thank you for any hint or help! :-)
Edit: It's becoming really interesting now. I have stepped into every single function just right before the message is printed and I ended up with these error messages:
at this location:
When I navigate through the call stack in QtCreator the error is printed again and again everytime I select another function in the stack.
Does this mean that the debugger is printing the message and that it is simply too stupid to resolve some sort of vtable stuff for me or does this mean that I have serious trouble going on?
Cause:
Somewhere in your code , you might have overrun the actual memory
Example 1 :
int elmArray[10];
for(int i = 0; i < 20; ++i)
{
elmArray[i] = 0;
}
In the above case, actual array size is 10 but we are assigning values to the index beyond 10.
Example 2:
char* cpyString;
strcpy(cpyString , "TEST");
These scenarios might end up in writing the values into other objects. Mostly could corrupt the virtual table.This gives the above warning.
Fix:
As you know, just correct the code as below.
Example :
int elmArray[10];
for(int i = 0; i < 10; ++i)
{
elmArray[i] = 0;
}
char cpyString[10];
strcpy(cpyString , "TEST");
In your case seems like, you are assigning the QTString::shared_null to some uninitialized string.
There are various threads on different websites where the
can not find linker symbol for virtual table
problem is discussed. Few explain why the problem exists, although some solutions are given to specific examples. Having experienced difficulty with this, I would like to share what I have learned.
First this error message only appeared for Linux builds, it did not show up for Windows builds.
In my case the problem was caused by a second call into a non-reentrant method from the same thread. Once I found the problem, it was easy to fix by using a static busy flag, and simply returning when busy was called a second time. In a nutshell that was the problem and solution. But how did I get into this mess?
Well the non-rentrant method was actually a Qt slot. Since I knew there was a possibility of the second call (actually an emit) being made from the first, the connect was set up with Qt::QueuedConnection. However, I later put up a splash screen QSplashScreen while the function was processing. Little did I realize that QSplashScreen::repaint() called QApplication::processEvents() which dispatched the second offending emit.
So I could have fixed the problem by removing the QSplashScreen and using a QLabel. However, while either works nicely in Windows, neither actually works in Linux, they put up a semi-transparent window and don't paint the contents (even repaint() and or processEvents() doesn't do it). So that is probably a Qt Linux bug, which is another story.

Child objects are (seemingly) randomly set to NULL or an 'illegal object'; how to debug that?

I use Cocos2d-x for a game which I am porting from Cocos2d-iphone. The original programmer seems to have used the 'feature' of Objective-C to not crash on calls to nil objects as a way to do a lot of sloppy things.
If this is related to that I don't know, however, in my code I never call release() manually and certainly not delete or anything like that. I don't even call ->removeObject() at all (although that would not result in the same issue as I have).
Now the problem: when the game is running, at random moments (they won't be random but they seem that way now obviously) child nodes get set to NULL. And this does not only affect my code but als the Cocos2d internals. Example:
CCLog("----------------");
for(int j = 0; j < this->getChildren()->count(); j++)
{
CCObject *child = this->getChildren()->objectAtIndex(j);
EnemySprite *enemy = dynamic_cast<EnemySprite*>(child);
if (enemy != NULL) {
CCLog("Enemy with tag %d found", enemy->getTag());
}
}
EnemySprite *enemy = dynamic_cast<EnemySprite*>(this->getChildByTag(i));
if (enemy == NULL) {
CCLog("Now enemy with %d is NULL :(", i);
}
In the getChildren() look, all enemies with the tags are there and print this;
Enemy with tag 1000 found
Enemy with tag 1001 found
Enemy with tag 1002 found
During the game it'll show this a lot, until it shows this;
Enemy with tag 1000 found
Enemy with tag 1001 found
Enemy with tag 1002 found
Now enemy with 1001 is NULL :(
and crashes.
In my mind, this should be impossible with the above code as I just checked, verified and printed exactly that object...
But even more interesting (maybe only to me, maybe it's some stupid mistake), this
this->getChildByTag(i)
randomly goes wrong internally as well; traversing the children, it'll find a NULL and conk out on Cocos2d internal code:
if(pNode && pNode->m_nTag == aTag)
return pNode;
The pNode is then not NULL (that's why the asserts do not trigger) but looks like this:
http://o7.no/137JXC4 (screenshot)
The cocos2d::CCCopying thing is already stuff of nightmares for me in this project; every time I see it I know something is wrong and I have no clue how to find what it is.
I already added a breakpoint at the release() delete line; it's not being called. And I, like I said, am not doing anything like that manually.
I use Xcode / iOS to debug, but the behavior is the same on Android (but on my computer Eclipse is slower that Xcode, especially during debugging).
I understand it would be difficult to give me a solution / cause, however; I would be really happy if someone can tell me how to attack this issue. It happens randomly throughout the (quite large) codebase and I'm at a loss how to find this issue...
I hope someone can help!
At times dynamic_cast returns 0 even tough its argument was not 0. This happens for example when you're casting a super class to a subclass (so called "down casting"). Check this tutorial for more information: http://www.cplusplus.com/doc/tutorial/typecasting/
I can imagine that if the elements in your list have a generic (unrelated) super type, this can be the problem in your case.
As you say it's hard to tell, but here are two ideas.
You might try turning on guard malloc.
Alternatively, you might gain something from putting a static int counter in your suspect class's (like EnemySprite's) deconstructor/constructor to decrement/increment, and break/log when it falls below zero.
I only see the definition of j what is i?
I believe it crashes after CCLog("Now enemy with %d is NULL :(", i);
since this line already been logged, it definitely not crashing here.
CCObjects are subject to the AutoReleasePool by default, which means Cocos2D-x will manage when to release the object. If you use the static constructor for these objects, you can call object->retain() and object->release() so that you can manage the memory yourself.
Source: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Reference_Count_and_AutoReleasePool_in_Cocos2d-x
If something changes the enemy object to NULL, what I would do is setting a data breakpoint at address of enemy(for 1001). Than,
If breakpoint is hit, that might be a memory corruption.
If breakpoint is not hit and you get NULL, dig into getChildByTag(). What I would do then is replacing this->getChildByTag() with dynamic_cast<EnemySprite*>(this->getChildren()->objectAtIndex()) check if the is any difference.
In Build Settings->Other C Flags->Debug and add -o0 flag and try debugging.

Qt access violation 0xC0000005 after slot

I have an issue that i just figured out what to do, so maybe you can help me.
I am working on a application that connects to a database, displays the values and allowes the user to update/insert values.
I have a QTabView and inside one of the tabs there are four QTableWidget's.
Inside this Tables is sometimes (depends on the value of the database) a QComboBox to select some predefined Values.
I catch the QComboBox::selectedIndexChanged(int) with a QSignalMapper and have a slot connected to the QSignalMapper to give some information what table it was and what setting was changed. From time to time i create the SettingsMapper new (and delete it before that) to reset the 'outdated' mapper-combobox connections.
So the problem is, that when i change the index inside a combobox, the slot gets called and i can debug into the moc_*.cpp where the switch of the signal/slot connections is, but after that i get the access violation on address 0xC0000005 inside the dlls.
Here the call stack:
QtCored4.dll!6721af70()
[Frames below may be incorrect and/or missing, no symbols loaded for QtCored4.dll]
QtCored4.dll!67219fe5()
QtCored4.dll!67218f14()
QtCored4.dll!67218e48()
QtCored4.dll!6721903d()
QtCored4.dll!6720f874()
QtCored4.dll!6702429b()
QtCored4.dll!670316f3()
QtGuid4.dll!655b93f1()
QtGuid4.dll!650f99d0()
user32.dll!7e41885a()
user32.dll!7e41882a()
user32.dll!7e42b326()
msctf.dll!7472467f()
user32.dll!7e43e1ad()
user32.dll!7e43e18a()
QtCored4.dll!67234b9c()
user32.dll!7e42b372()
user32.dll!7e418734()
user32.dll!7e418816()
user32.dll!7e4189cd()
user32.dll!7e418a10()
QtCored4.dll!672359b6()
ntdll.dll!7c90cfdc()
ntdll.dll!7c958e0d()
ntdll.dll!7c95932a()
ntdll.dll!7c90cfdc()
ntdll.dll!7c9594ca()
ntdll.dll!7c919ca7()
ntdll.dll!7c918f01()
ntdll.dll!7c91925d()
ntdll.dll!7c918f01()
ntdll.dll!7c9101bb()
ntdll.dll!7c9192ef()
ntdll.dll!7c918f01()
ntdll.dll!7c9101bb()
user32.dll!7e4277b0()
user32.dll!7e4277f7()
ntdll.dll!7c90da0c()
kernel32.dll!7c8024c7()
msctf.dll!74725951()
msctf.dll!74725956()
user32.dll!7e418a80()
user32.dll!7e418734()
user32.dll!7e418816()
ntdll.dll!7c96c6a7()
QtCored4.dll!6723c8f6()
datProgram.exe!__tmainCRTStartup() Line 578 + 0x35 bytes C
datProgram.exe.exe!WinMainCRTStartup() Line 403 C
kernel32.dll!7c817067()
`
What makes me curios is, that in another tab is one QTableWidget with the same methods as described above, but the problem does not occur there.
And when running in release version(Ctrl+F5) the problem also seems to be gone ... ò.Ó
Any advice?
From time to time i create the SettingsMapper
new (and delete it before that) to reset
the 'outdated' mapper-combobox connections.
Do you by any chance delete the signal mapper from a slot called by signal sent from that signal mapper? That's not allowed, can't delete the instance when you are currently in a method of that instance.
Solution is to use deleteLater() instead. That will cause the object to be deleted when control returns to event loop.

"Debug Assertion" Runtime Error on VS2008?

I'm writing a C++ MFC program on VS2008 and I'm getting this "Debug Assertion Error" when I first run the program sometimes. When I try to debug it, it takes me to this winhand.cpp file which is not part of the program I wrote so I'm not sure how to debug this.
It takes the error to this place in winhand.cpp
CObject* pTemp = LookupTemporary(h);
if (pTemp != NULL)
{
// temporary objects must have correct handle values
HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset); // after CObject
ASSERT(ph[0] == h || ph[0] == NULL);
if (m_nHandles == 2)
ASSERT(ph[1] == h);
}
So why does this error happen? Why does it only happen sometimes (50% of the time)? How would I debug this?
I'll provide some code if is needed.
THANKS!
The code that is asserting is part of MFC's CHandleMap class. MFC deals with windows as CWnd objects, but Windows deals with them as HWND handles. the handle map allows MFC to 'convert' an HWND into a pointer to the MFC object representing that object.
What the assertion seems to be doing is checking that when a lookup of the handle finds an MFC object, that the MFC object also thinks it's wrapping the same handle.
If they're different, then you get the assertion.
So it would appear that something is corrupting the handle map or the MFC object for that handle or you're doing something incorrect that gets these 2 data structures out of sync.
Some things you might do to try to debug the problem is to determine:
what MFC object is being found in the lookup (that's what's being pointed to by pObject)
what the MFC object thinks it's wrapping (that's the handle ph[0] and/or ph[1] - I'm not sure why there can be 2 of them)
what the handle is for (that's h)
Do the handles look like handle values or do they look like garbage? Does pObject point to something that looks like an MFC object, or garbage? Do any of these these things seem related?
The answers to these questions may point to what you need to do next (maybe set a debug write breakpoint on the item that looks like it's trashed).
I got this same assertion few days ago, and after some google search,
I found the solution for my case here:
http://forums.codeguru.com/showthread.php?216770-What-would-cause-this-assertion
In my case, change to misused
CDC* dc = GetDC();
CSize spaceSize = dc->GetTextExtent(" ");
dc->DeleteDC();
to
CDC* dc = GetDC();
CSize spaceSize = dc->GetTextExtent(" ");
ReleaseDC(dc);
would fix it.
Look out for code along those lines (from memory from Stroustrup's book):
c1 = (t2+t3).c_str();
(in spirit, could be other commands and expressions of course).Temporary objects are destroyed after their enclosing full expression has been evaluated, or at least the standard allows them to be. That means that what you would like to allocate to c1 may, or may not, still be in memory where it can be assigned to c1. The compiler may alert you to this issue, and the issue may or may not arise depending on what exactly you assign and other circumstances (I am not compiler writer), which would also explain why you get this error message only sometimes.
So in your shoes, I'd scan my code for similar expressions and clean them up.
When the debugger breaks, head up the call stack to the first bit of your code (if there is any - hopefully there is!). Ideally it's as simple as something in your code calling a library function incorrectly, and the library is catching the error with an assert and alerting you to that. (I don't think anyone will be able to tell what's wrong from the library code, we need to see your code.)
Otherwise, you're in for some tricky debugging: you're doing something wrong with the library that is asserting (looks like MFC) so go back and review all your MFC code and make sure everything is correct and according to the documentation.
This looks suspiciously like an error I had this morning. Is this happening in OnIdle()?
I know this is a very old post, but hoping that someone may get a little help from my answer.
I also faced a similar issue recently because of my simple mistake, then I came across this post and got a hint from "pac"'s post.
What I found is that if I use DeleteDC() to release DC returned from GetWindowDC() or GetDC() I will get the above assertion in MFC frame once CPaintDC object instance goes out of scope.
CDC * pDC = GetWindowDC();
...
ReleaseDC(pDC);
You have to use DeleteDC() only in conjunction with CreateDC() API.
CDC * pDC = new CDC();
pDC->CreateDC();
....
pDC->DeleteDC();
We had this problem when some of our project dlls were linking MFC as static library and some as shared library (check "Use of MFC" in Project settings)