Bug in QtCreator, MingGW and/or gdb?
-
I posted on this topic earlier under "can't find linker symbol for virtual table," but I've pared the problematic code down to such an extent that I don't see how the problem could be in my code -- although I would be happy to hear where I went wrong...
I am running Windows 7, Qt 5.0.1 and MinGW.
When I execute the code in debug mode under QtCreator, I get the error
@can't find linker symbol for virtual table forQWidget' value found
QMenuPrivate::popupGeometry(int) const' instead
@as "Application Output" when I hit the breakpoint that I point out below in the code.
main.cpp:
@#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}@mainwindow.h:
@#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QtWidgets>
#include <QMainWindow>class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
MainWindow(QWidget *parent = 0);private slots:
void closeTextTab(int index);
void render2DMenuSlot();private:
QMenu *actionMenu;
QAction *render2DAction;QTabWidget *textTabs;
};
#endif // MAINWINDOW_H@
mainwindow.cpp:
@#include "mainwindow.h"
#include "codeitem.h"
#include "noteswidget.h"
#include "interpreter.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
render2DAction = new QAction(tr("&Render - 2D"),this);
connect(render2DAction,SIGNAL(triggered(bool)),this,SLOT(render2DMenuSlot()));actionMenu = menuBar()->addMenu(tr("&Action"));
actionMenu->addAction(render2DAction);
}void MainWindow::closeTextTab(int index)
{
}void MainWindow::render2DMenuSlot()
{
// This is where the error manifests. Put a breakpoint here,
// before any of the code below executes, and you get the
// can't find linker symbol for virtual table for `QWidget' value
// error.
QWidget* curWidget = textTabs->currentWidget();
CodeItem ti = qobject_cast<CodeItem>(curWidget);// The code below is non-functional garbage, but somehow removing
// it eliminates the error above. Moreover, even before I pared the underlying
// functionality away and the code below worked, I got the error above.
bool hasErrors = false;
QString errors;
Interpreter* interp = NULL;try {
try {
interp = new Interpreter();
} catch (QString e) {
errors = e;
hasErrors = true;
}if (hasErrors == false) { int* sigs = interp->nextStatementToSignals(); while (true) { delete sigs; sigs = interp->nextStatementToSignals(); } }
} catch (QString e) {
} catch (...) {
}
}@Now some .h files for three classes, all of which do essentially nothing, but eliminating them from the project also eliminates the error.
@#ifndef INTERPRETER_H
#define INTERPRETER_H#include <QString>
class Interpreter
{
public:
Interpreter() throw(QString);
int* nextStatementToSignals();
};#endif // INTERPRETER_H
#ifndef NOTESWIDGET_H
#define NOTESWIDGET_H#include <QtWidgets>
class NotesWidget : public QWidget
{
Q_OBJECTpublic:
explicit NotesWidget(QWidget *parent = 0);
};#endif // NOTESWIDGET_H
#ifndef CODEITEM_H
#define CODEITEM_H#include <QtWidgets>
#include "noteswidget.h"
class CodeItem : public NotesWidget
{
Q_OBJECTpublic:
CodeItem();
};#endif // CODEITEM_H@
The three .cpp files that go with these classes don't do anything either:
@#include "interpreter.h"
Interpreter::Interpreter() throw(QString)
{
}int* Interpreter::nextStatementToSignals()
{
return NULL;
}#include "noteswidget.h"
NotesWidget::NotesWidget(QWidget *parent) : QWidget(parent)
{
}#include "codeitem.h"
CodeItem::CodeItem() : NotesWidget()
{
}@For completeness, here's the .pro file:
@QT += core gui widgetsTARGET = vcnctest
TEMPLATE = appSOURCES += main.cpp
mainwindow.cpp
codeitem.cpp
noteswidget.cpp
interpreter.cppHEADERS += mainwindow.h
codeitem.h
noteswidget.h
interpreter.h @So, the program does nothing but open up an empty window with a single menu choice that routes to MainWindow::render2DMenuSlot(). As soon as the debugger hits the breakpoint at the start of that method, you get the error. It's true that, as the code above stands, the method is garbage (the various pointers will be NULL), but that's because I pared away every bit of functionality to get to cause of the error message. In any case, an error shouldn't appear before you get to any of the code in the method.
I thought that there might be something going on in moc_window.cpp, so I put a breakpoint at the start of MainWindow::qt_static_metacall(). At the line
@_c == QMetaObject::InvokeMetaMethod@I get a similar error:
@can't find linker symbol for virtual table forMainWindow' value found
_q_ObjectMutexPool' instead@For reference, this is the complete method from moc_mainwindow.cpp:
@void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
MainWindow *_t = static_cast<MainWindow *>(_o);
switch (_id) {
case 0: _t->closeTextTab((reinterpret_cast< int()>(_a[1]))); break;
case 1: _t->render2DMenuSlot(); break;
default: ;
}
}
}@If I continue stepping into the case _t->render2DMenuSlot(), that's were the original error appears:
@can't find linker symbol for virtual table forQWidget' value found
QMenuPrivate::popupGeometry(int) const' instead@Yes, after paring away so much of the original program's functionality, the program above is garbage, but these errors are out of left field. I don't see how they could be due to anything other than a problem in the development framework.
-
It would be simpler if you would simply upload your project here (unless it's top secret).
For now i get segmentation fault on line 25 in mainwindows.cpp becouse of uninitialized pointer textTabs.
@
can't find linker symbol for virtual table forQWidget' value found
QMenuPrivate::popupGeometry(int) const' instead
@is printed as well.
If render2DMenuSlot is empty everything works well.
-
After posting the above, it bothered me that the program is non-functional. By adding a couple of lines, the program can be made functional -- it doesn't do anything useful, but it shouldn't crash either.
Add a single line to mainwindow.h:
@CodeItem *bogusItem;@and a few lines to MainWindow's constructor:
@
textTabs = new QTabWidget();
bogusItem = new CodeItem();
textTabs->addTab(bogusItem,"Junk");@and MainWindow::render2DMenuSlot() should no longer crash. Again, this really shouldn't have anything to do with the error I get (and I do still get it after these changes).
-
8majkel8, yes you would get a segmentation fault there, but the error occurs before that point. I just posted a couple of minor changes you could make to the source that so that these spurious errors that are unrelated to the real problem don't arise. Here's the new version of render2DMenuSlot();
@
void MainWindow::render2DMenuSlot()
{
QWidget* curWidget = textTabs->currentWidget();
CodeItem ti = qobject_cast<CodeItem>(curWidget);bool hasErrors = false;
QString errors;
Interpreter* interp = NULL;try {
try {
interp = new Interpreter();
} catch (QString e) {
}if (hasErrors == false) { int* sigs = interp->nextStatementToSignals(); if (sigs == NULL) // It will be NULL, so the method returns. return; while (true) { delete sigs; sigs = interp->nextStatementToSignals(); } }
} catch (QString e) {
}@Yes, emptying render2DMenuSlot() eliminates the error, and that's part of the mystery. Since the error happens before any code there is executed it shouldn't have anything to do with it.
Posting the entire project in its original form would only confuse things. The code above should work (even if it does nothing).
-
This looks more an more like a bug somewhere outside of my code. I reported it in the Qt Bug Tracker. See it
"here":https://bugreports.qt-project.org/browse/QTCREATORBUG-9555You can download the complete project there.
-
It does look like a bug in the Qt library or compiler. (Not Qt Creator, by the way -- Qt Creator is just the IDE that provides the text editor and integrates your chosen compilation toolchain, debugger, version control system, and Qt libraries)
I recently encountered strange crashes when launching dialogs. I was never able to track down the root cause, but I made the problem go away by connecting my dialog-launching slots using QueuedConnections -- this lets other code finish before the dialogs get launched.