Can't find linker symbol for virtual table
-
The subject line gives the error I get when running my program in debug mode in QtCreator. After stripping away nearly all of the original program, the error is due to something in the code below. Whatever is causing this error, it is "fragile," meaning that things that seem to be unrelated affect whether or not the error appears. The program seems pretty innocuous and that's what makes it so puzzling.
I am on Windows 7, 64 bit, running Qt 5.0.1.
Here's main.cpp -- the usual:
@
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}@Next is mainwindow.cpp. This is where the error manifests itself, even it the cause is not here.
@
#include "mainwindow.h"
#include "codeitem.h"
#include "noteswidget.h"
#include "interpreter.h"
#include "bogusresult.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
createActions();
createMenus();textTabs = new QTabWidget;
textTabs->connect(textTabs,SIGNAL(tabCloseRequested(int)),
this,SLOT(closeTextTab(int)));CodeItem *codeWidget = new CodeItem();
(void) textTabs->addTab(codeWidget,"New");setCentralWidget(textTabs);
}MainWindow::~MainWindow()
{
}void MainWindow::createActions()
{
render2DAction = new QAction(tr("&Render - 2D"),this);
connect(render2DAction,SIGNAL(triggered(bool)),this,SLOT(render2DMenuSlot()));
}void MainWindow::createMenus()
{
actionMenu = menuBar()->addMenu(tr("&Action"));
actionMenu->addAction(render2DAction);
}// Now a whole bunch of empty methods, which I omit for brevity.
// What's odd is that if I get rid of the function declarations in the .h file, and
// the (empty) function definitions here, then the error goes away. All of these
// functions return either void or bool, so they really don't have anything to
// do with the cause of the problem, even if they have something to
// do with how it manifests.void MainWindow::render2DMenuSlot()
{
// This is where the error appears. I set the only breakpoint in the program at
// this line (before the line below is executed) and it says
// can't find linker symbol for virtual table forQWidget' value // found
QMenuPrivate::popupGeometry(int) const' instead
//
// Another weird thing is that if I get rid of just about any of the code below
// the first two lines, then the error disappears -- maybe the compiler is
// optimizing away the problem, whatever it is.
//
// None of the classes below, aside from CodeItem, actually do anything.
// Interpreter is defined as an empty do-nothing class, as is BogusResult. If you tried to
// actually run the code below, it would crash since all the pointers will be NULL,
// but that shouldn't affect the fact that you get an error at the very beginning.QWidget* curWidget = textTabs->currentWidget();
CodeItem ti = (CodeItem) curWidget;bool hasErrors = false;
QString errors;
Interpreter* interp = NULL;try {
try {
interp = new Interpreter(QString(),true,1,NULL,NULL,NULL,0.0,0.0,0.0);
} catch (QString e) {
errors = e;
hasErrors = true;
}if (hasErrors == false) { BogusResult* sigs = interp->nextStatementToSignals(); while (sigs->cmd->type != Statement::EndOfFile) { delete sigs; sigs = interp->nextStatementToSignals(); } }
} catch (QString e) {
} catch (...) {
}
}
@mainwindow.h is:
@#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QtWidgets>
#include <QMainWindow>class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
MainWindow(QWidget *parent = 0);
~MainWindow();private slots:
void render2DMenuSlot();// As noted in mainwindow.cpp, there are a bunch of irrelevant declarations made
// here too, which I omit. They have nothing to do with the problem, since the
// definitions are all empty, although removing them does make the error go away.private:
void createActions();
void createMenus();QMenu *actionMenu; QAction *render2DAction; QTabWidget *textTabs;
};
#endif // MAINWINDOW_H
@Here are the .h and .cpp files for CodeItem. After stripping most of the code away to make the error easier to find, this is just a wrapper around NotesWidget. First, the .h file:
@#ifndef CODEITEM_H
#define CODEITEM_H#include <QtWidgets>
#include "noteswidget.h"
class CodeItem : public NotesWidget
{
Q_OBJECTpublic:
CodeItem();
};#endif // CODEITEM_H
@And the .cpp file:
@
#include "codeitem.h"CodeItem::CodeItem() : NotesWidget()
{
// Nothing to do...
}
@Now noteswidget.h:
@#ifndef NOTESWIDGET_H
#define NOTESWIDGET_H#include <QtWidgets>
class NotesWidget : public QWidget
{
Q_OBJECTprivate:
QTextEdit theText;
QTextEdit notes;
QHBoxLayout theLayout;
QVBoxLayout leftLayout;public:
explicit NotesWidget(QWidget *parent = 0);private slots:
void markDirty();
void contentsScrolled(int v);
};#endif // NOTESWIDGET_H
@And noteswidget.cpp
@
#include "noteswidget.h"NotesWidget::NotesWidget(QWidget *parent) : QWidget(parent)
{
theText.verticalScrollBar()->connect(theText.verticalScrollBar(),
SIGNAL(valueChanged(int)),
this,SLOT(contentsScrolled(int)));theText.connect(&theText,SIGNAL(textChanged(void)),this,SLOT(markDirty(void)));
leftLayout.addWidget(¬es);
theLayout.addLayout(&leftLayout);
theLayout.addWidget(&theText);this->setLayout(&theLayout);
}void NotesWidget::contentsScrolled(int v)
{
}void NotesWidget :: markDirty()
{
}
@This is for the code. After stripping things down, there's not much left. I don't see a problem with any of this, but I am new to Qt.
-
Which class is the linker having problems with? Each class will have its own "virtual table":http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/. Have a look at your error message again, and you should be able to narrow down the culprit.
Anyway, the most common cause of this error in Qt is described "here":http://qt-project.org/doc/qt-5.0/qtdoc/debug.html#common-bugs (see "common bugs"). To fix it, run qmake and then rebuild. In Qt Creator, make sure your project is the active one (or the only one open), and do:
Build -> Clean Project 'XYZ'
Build -> Run qmake
Build -> Build Project 'XYZ'
-
I don't think the problem is due to the build process. I've done what you suggest, and I've also tried quitting out of Qt, and removing all files except for the source files and the .pro file, so that it's a completely fresh build.
The complete message is
can't find linker symbol for virtual table for
QWidget' value found
QMenuPrivate::popupGeometry(int) const' insteadI can't even say for sure which class is causing the problem because the message is so vague. It turns out that if I strip away even more code, I still have the error. Even if the functions of NotesWidget, including the constructor, are blank and do nothing and the constructor of MainWindow does nothing but create the single menu choice, I still get the error.
At this point my guess is that the problem has something to do with the sub-classing: CodeItem is a sub-class of NotesWidget , which is a sub-class of QWidget. Aside from the menu-related message passing, that's about the only thing left in the program.
-
JKSH, you got me thinking about what's going on with the moc files, so I put breakpoints in every method of every moc file, even though I have no clear idea what sort of magic is happening in these files. I observed two things.
First, when the breakpoints are invoked for certain methods in moc_mainwindow.cpp, I get
Internal error: pc [various numbers] in read in psymtab, but not in symtab.
The "various numbers" were either 0x0 or 0x67.I chalked that up to gdb weirdness and got rid of any breakpoint that leads to that message when the program launches. Now, when I invoke the menu choice leading to the original error, I find myself at the beginning of
MainWindow::qt_static_metacall()
which seems to be some kind of routing function. At that point I getcan't find linker symbol for virtual table for
MainWindow' value found
_q_ObjectMutexPool' insteadThis is a different error in terms of the specifics (MainWindow instead of QWidget), but it's the same type of error -- something about the "linker symbol for virtual table."
-
Ah, it's a runtime error message. Sorry, I thought it was a compile-time message.
Anyway, from other similar cases (e.g. "here":http://www.qtcentre.org/threads/50592-can-t-find-linker-symbol-for-virtual-table-for-QString-Data-value and "here":http://qt-project.org/forums/viewthread/4553 -- Googling error messages is usually very useful), it sounds like you might have a pointer/memory bug. These are nasty because they're hard to track down, as you've found: When you simplify your code and recompile, the memory layout gets rearranged, so an error/crash that popped up in one place before may pop up at a different place now. Check your memory management and your typecasts.
Possibly useful tidbit: When a QObject is destroyed, it will also free its children QObjects. Make sure you're not accessing a destroyed child object.
I don't know if this are related to your issue or not, but I noticed this:
[quote]
@
CodeItem ti = (CodeItem) curWidget;
@
[/quote]NEVER ever use C-style casts -- they are unsafe, and a source of many problems. Use qobject_cast<> instead.You're right in saying that MainWindow::qt_static_metacall() is a "routing function". If you're interested in demystifying signal/slot connections, here's an "excellent blog post":http://woboq.com/blog/how-qt-signals-slots-work.html that explains the internals.
-
The C-style cast is not the problem. I did change it to q_object_cast() and still get the error. I've managed to pare away even more of my code and still get the error. At this point, the only code that's ever executed is what sets up the menus and shows the single empty window. Let me clean it up some more to make it as brief as possible and I will post it all. I'm starting to think that there's a bug somewhere other than in my code.
-
JKSH, if you are following this, see the new thread I started: "Bug in QtCreator, MingGW and/or gdb?" I've shrunk down the source code to almost nothing, and the error is still present.
-
This problem may arise when the version of the qtcore.dll differ from that of the qtscript.dll. Check if your program used qtcore4.dll but linked to qtscriptD4.dll, meaning that you mixedly use Debug and Release dlls. I also have this problem and checked my program.exe by Dependency Walker provided by VisualStudio, and turn out to found that mixedly use problem. Hope to be helpful.