I have a very strange problem while trying to run a QProcess in a class HmiApplication, which is derived from QApplication.
The application throws a SIGSEGV in line 6 of main.cpp. This occurs only if line 11 of hmiapplication.cpp is commented out (If I don't qDebug() the stdout of the QProcess).
For the sake of simplicity and clarity, I didn't handle any return values while creating the QProcess.
main.cpp
#include "hmiapplication.h"
int main(int argc, char **argv)
{
HmiApplication hmi(argc, argv);
return hmi.exec(); // LINE 6 - SIGSEGV
}
hmiapplication.h
#ifndef HMIAPPLICATION_H
#define HMIAPPLICATION_H
#include <QApplication>
#include <QProcess>
class HmiApplication : public QApplication
{
Q_OBJECT
public:
HmiApplication(int argc, char **argv);
virtual ~HmiApplication();
private:
QProcess *macFinder = nullptr;
};
#endif // HMIAPPLICATION_H
hmiapplication.cpp
#include "hmiapplication.h"
HmiApplication::HmiApplication(int argc, char **argv) : QApplication(argc, argv)
{
macFinder = new QProcess(this);
macFinder->start("arping", QStringList() << "-c 2" << "192.168.1.1");
macFinder->waitForReadyRead();
QString ret(macFinder->readAllStandardOutput());
ret = ret.mid(ret.indexOf('[') + 1, 17);
qDebug() << ret; // LINE 11
}
HmiApplication::~HmiApplication()
{
}
EDIT:
If I add QVector<Camera*> cameras; to the header and
for(quint8 i = 0; i < 10; i++) {
Camera *cam = new Camera(i);
cameras.append(cam);
}
to the source file, it doesn't matter whether or not I remove the qDebug() line and will throw a segmentation fault in both cases.
Camera is a derived class of QLabel and is perfectly working without the QProcess mentionened above.
The QApplication constructor accepts its first parameter by reference...
QApplication::QApplication(int &argc, char **argv)
With the documentation also warning that...
The data referred to by argc and argv must stay valid for the entire
lifetime of the QApplication object. In addition, argc must be greater
than zero and argv must contain at least one valid character string.
However, you pass argc by value to the HmiApplication. Hence the QApplication constructor receives a non-const reference to the local copy which will go out of scope at the end of the HmiApplication ctor leading to undefined behaviour later on.
Change the signature of your constructor to...
HmiApplication::HmiApplication(int &argc, char **argv)
Related
Could anybodyy help me with this problem? I am trying to run an application using the cmakefiles. on the main file of my program I get a segmentation fault when the program gets to the line of code to execute the QAppication. Here is the fragment code below:
int main(int argc, char** argv)
{
bool viewing;
parse_command_line( argc, argv );
#ifdef _GRAPHICS_
glutInit(&argc, argv); // note the code runs correctly when this line is excluded and the glutInit was initialized in another class named Viewer (See class Viewer instantiated below), however for my specific application I need to initialize the glutInit in the main program
#endif
if( viewing )
{
#ifdef _GRAPHICS_
QApplication application(argc, argv);
Viewer *viewer = new Viewer( 0, exp, argc, argv );
Interface *render = new Interface( 0, exp, viewer );
render->show();
return application.exec(); //this line causes the segmentation fault
delete viewer;
delete render;
#endif
}
}
When glutInit is called inside Viewer, application and viewer receive all the command line arguments. When you call it before, like you do, glutInit will eat all the parameters it understands, so the other objects might miss some arguments.
Possible solutions: do the glutInit (after application creation), or make a copy of argc/argv.
I have just started developing using QtGUI and I have checked out some tutorials and documentation, and by what I've read this should work.
#define CONNECT QObject::connect
void test();
QPushButton *lpTestBtn;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtProject w;
w.show();
lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
CONNECT(lpTestBtn, SIGNAL(clicked()),qApp,SLOT(test()));
return a.exec();
}
void test()
{
lpTestBtn->setText("Hi");
}
But test() never gets called. Also, lpTestBtn is not null and is found correctly.
I have tried the following changes
CONNECT(lpTestBtn, SIGNAL(clicked()),qApp->activeWindow(),SLOT(test()));
CONNECT(lpTestBtn, SIGNAL(clicked()),w.window(),SLOT(test()));
I know I can just do QtProject::on_TestBtn_clicked(); but I'd like to get it working using CONNECT,SIGNAL and SLOT.
The test function in your code is not a slot, nor does it belong to the Q(Core)Application class as you seem to have used it.
The best would be is to move that one line in the test function to the connection with the lambda syntax. This will require C++11 support, but that is in quite common use these days.
You would use the new shiny signal-slot syntax. This would spare you some headache for runtime issues in the future because they would appear at compilation-time.
Therefore, you would write something like this:
main.cpp
#include <QMainWindow>
#include <QApplication>
#include <QPushButton>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
// Replace it with "QtProject".
QMainWindow w;
w.show();
QPushButton * lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
QObject::connect(lpTestBtn, &QPushButton::clicked, [=]() {
lpTestBtn->setText("Hi");
});
return a.exec();
}
main.pro
TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Please also note that it is bad idea to create a global pointer for a QPushButton object. It not only leaks the memory, but you could have other issues, too.
1) QApplication doesn't have a test() slot in it. You need to make your own class, inheriting QApplication, and give that class a test() slot. What you've done is create a regular function, which won't help.
2) You didn't check the return value of connect, which means you didn't see that it was giving you an error, which would probably have given you some clues.
You can connect signals to the slots which are in classes derived from QObject so meta compiler can deduce slot calls. But your test() is global function. You have to put your slot function inside a class that derives from QObject and supports Q_OBJECT macro or define a lambda function ( with C++11 support) as Laszlo Papp showed.
Example:
// testwrapper.h
class TestWrapper : public QObject
{
Q_OBJECT
//...
public slots:
void test();
};
// main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtProject w;
w.show();
QPushButton * lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
TestWrapper tw;
CONNECT( lpTestBtn, SIGNAL( clicked()),tw,SLOT( test()));
return a.exec();
}
I am new at Qt (and c++). I have a simple question:
What is wrong?
#include <QCoreApplication>
#include <QtNetwork/QLocalServer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QLocalServer* x = new QLocalServer(this);
return a.exec();
}
Thank for advice.
Your problem is this (pun intended):
QLocalServer* x = new QLocalServer(this);
this is not valid outside non-static class member functions. main() is not a member function, and thus this doesn't exist. You can pass NULL pointer instead, to signify that the object shall have no parent:
QLocalServer* x = new QLocalServer(NULL);
Don't forget to add the network module in your project file's QT variable. For example:
QT += OTHER_MODULES_YOU_USE_HERE network
I managed to write a "Gui Unit Test" using this tutorial. However, when I compile my code I get this:
PASS : testUnits::initTestCase()
PASS : testUnits::toUpper()
QFATAL : testUnits::testGui() QWidget: Must construct a QApplication before a QPaintDevice
FAIL! : testUnits::testGui() Received a fatal error.
Unknown file(0) : failure location
Totals: 2 passed, 1 failed, 0 skipped
********* Finished testing of testUnits *********
why is it giving me: Must construct a QApplication before a QPaintDevice ?
it works now, here is my Gui unit test function definition:
void testUnits::testGui(){
QLineEdit lineEdit;
QTest::keyClicks(&lineEdit,"hellow world");
QCOMPARE(lineEdit.text(), QString("hello world"));
}
and here is how my main() looked like before fixing the problem :
int main(int argc, char *argv[])
{
testUnits testString;
QTest::qExec(&testString, argc, argv);
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
So, when I compile the code, it execute the unit test before constructing the QApplication.
Therefore I put my QTest::qExec() after QApplication and now it works and the main() looks like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
testUnits testString;
QTest::qExec(&testString, argc, argv);
return a.exec();
}
It's better to not define your own main manually. All of the test logic, including the required preconditions, shall be made within the test object (the QObject subclass with the test* slots) itself. See the QTestLib manual for details.
If you do this, then simply using the QTEST_MAIN will do the right thing and save you some time.
I'm trying to learn Qt, with a fairly simple application:
#include <QtGui/QApplication>
#include <QPushButton>
#include <QDebug>
/* -- header begin {{{ */
class BareBase {
public:
BareBase();
};
class BareBones: public QApplication {
private:
BareBase* base;
public:
BareBones(int &argc, char **argv);
~BareBones();
};
/* -- header end }}} */
/* -- implementation begin {{{ */
BareBase::BareBase()
{
QPushButton hello("Hello world!");
hello.resize(100, 30);
hello.show();
}
BareBones::BareBones(int& argc, char** argv): QApplication(argc, argv)
{
qDebug() << "Creating new instance ... ";
base = new BareBase();
}
BareBones::~BareBones()
{
qDebug() << "Cleaning up ... ";
delete base;
}
/* -- implementation end }}} */
int main(int argc, char **argv)
{
//Q_INIT_RESOURCE(files);
BareBones app(argc, argv);
return app.exec();
}
Now, the problem is that the Button created in BareBase never shows up, and i'm puzzled why?
Your QPushButton is creating and display correctly but go out of scope when leaving BareBase constructor. Using a member variable or a pointer will solve your problem.
If you use a pointer, you should add your button to its parent. By this way the button will be automatically deleted when the parent will be deleted.
QPushButton might have shown up but not in the visible area of the widget. That's why, you should add all your widgets to the Layouts that are available in Qt to obtain the desired behaviour. Check out the docs here... It has examples also...
Also, basically you will be having a base QWidget or most probably QMainWindow on which all your controls will be present.. So, your QPushButton will be in the parent widget.. Your QApplication will contain your application specific information like setting the window, setting the font for your entire application kinda stuff..
Hope it helps..