我想编写一个方法来创建一个按钮并将其连接到一个带有字符串的插槽:
void Widget::createButton(const char *member)
{
QPushButton *button = new QPushButton(this);
QSignalMapper *signalMapper = new QSignalMapper(this);
signalMapper->setMapping(button, "Test");
connect(signalMapper, SIGNAL(mapped(QString)), this, member);
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
}
void Widget::sendCom(QString data)
{
std::cout << data << std::endl;
}
Widget
在(只是一个子类)的一个实例上QWidget
我做:
widget->createButton(SLOT(sendCom(QString))
如果没有映射,它可以正常工作,我从一段类似的代码中复制了映射语法,该代码也可以正常工作。编译时没有错误,但是当我按下按钮时,我最终会出现分段错误。有任何想法吗?
编辑:就像 peppe 建议的那样,我运行了 valgrind,这是输出
==31303== Invalid read of size 8
==31303== at 0x3E1632DBF0: QAbstractButton::text() const (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x407A66: Widget::sendCom(QString) (widget.cpp:36)
==31303== by 0x40804E: Widget::qt_metacall(QMetaObject::Call, int, void**) (moc_widget.cpp:72)
==31303== by 0x3E0FB6A7DE: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6DEE4: QSignalMapper::mapped(QString const&) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6E009: QSignalMapper::map(QObject*) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6F23F: QSignalMapper::qt_metacall(QMetaObject::Call, int, void**) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6A7DE: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E165DCE51: QAbstractButton::clicked(bool) (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x3E1632E75A: ??? (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x3E1632FADA: ??? (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x3E1632FD4B: QAbstractButton::mouseReleaseEvent(QMouseEvent*) (in /usr/lib64/libQtGui.so.4.6.2)
==31303== Address 0x8 is not stack'd, malloc'd or (recently) free'd
==31303==
==31303==
==31303== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==31303== Access not within mapped region at address 0x8
==31303== at 0x3E1632DBF0: QAbstractButton::text() const (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x407A66: Widget::sendCom(QString) (widget.cpp:36)
==31303== by 0x40804E: Widget::qt_metacall(QMetaObject::Call, int, void**) (moc_widget.cpp:72)
==31303== by 0x3E0FB6A7DE: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6DEE4: QSignalMapper::mapped(QString const&) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6E009: QSignalMapper::map(QObject*) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6F23F: QSignalMapper::qt_metacall(QMetaObject::Call, int, void**) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E0FB6A7DE: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib64/libQtCore.so.4.6.2)
==31303== by 0x3E165DCE51: QAbstractButton::clicked(bool) (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x3E1632E75A: ??? (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x3E1632FADA: ??? (in /usr/lib64/libQtGui.so.4.6.2)
==31303== by 0x3E1632FD4B: QAbstractButton::mouseReleaseEvent(QMouseEvent*) (in /usr/lib64/libQtGui.so.4.6.2)
这有助于定位地址,但我仍然不知道如何调试。
编辑:问题解决了。我缩短了代码以更精确,但这隐藏了实际原因
Create Button actually looked like this:
void Widget::createButton(const QString &text, int x, int y, const char *member, QString &data)
{
QPushButton *button = new QPushButton(this);
signalMapper = new QSignalMapper(this);
signalMapper->setMapping(button, data);
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(sendCom(QString)));
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
button->setText(text);
button->move(x, y);
button->show();
}
void Widget::sendCom(QString data)
{
QPushButton *clickedButton = qobject_cast<QPushButton *>(sender());
std::cout << qPrintable(data) << std::endl;
std::cout << qPrintable(clickedButton->text()) << std::endl;
}
qobject_cast 导致了 SIGSEGV。它仍然是为了澄清它为什么这样做。