PDA

View Full Version : My application crashes



sophister
26th April 2009, 13:34
I have write a application in which user can add QToolButton into the UI dynamic. But there is something wrong seriously with my application.
It often crashes!!
The following is what I get from the DOS output:

H:/QTprojects/testdynamic/debug/testdynamic.exe exited with code 1073807364
in which testdynamic.exe is the application I write.
Do some guys know the reason?
Thanks a lot!

caduel
26th April 2009, 13:46
You made a programming mistake? :p

If you show us some code, maybe we can point you to what that mistake is!

sophister
26th April 2009, 16:01
Thanks! I agree with you. The following is my code:

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindowClass)
{
ui->setupUi(this);

}

MainWindow::~MainWindow()
{
delete ui;
}

bool MainWindow::on_addExeButton_clicked()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Choose the application"), tr("."), tr("Excutable(*.exe)"));
if(filename.isNull())
return false;
//user choose an excutive application
QFileInfo fileInfo(filename);
QFileIconProvider seekIcon;
QIcon icon = seekIcon.icon(fileInfo);
QToolButton *btn = new QToolButton;
btn->resize( 300, 300);
btn->setIcon(icon);
//if user click the corresponding button, this app will run the chosen application
connect(btn, SIGNAL(clicked()), this, SLOT(callExe()));
buttons.insert(filename, btn);
ui->verticalLayout1->addWidget(btn);
ui->verticalLayout1->addStretch();
}

void MainWindow::callExe()
{
qDebug() << "Ready to execute program";
QToolButton *sender = static_cast<QToolButton*>(this->sender());
QString path;
QMapIterator<QString, QToolButton *> i(buttons);
while(i.hasNext())
{
if(i.peekNext().value() == sender)
{
path = i.next().key();
qDebug() << "Find the path!!\n";
break;
}
}

if(path.isEmpty())
{
qDebug() << "******File path is null!!";
return;
}
//run the corresponding application
// QObject *parent = NULL;
// QString program = "J:\\2\\exeshan\\Debug\\11.ppt";
QStringList arguments;
arguments << "-style" << "motif";
QProcess *myProcess = new QProcess(this);
myProcess->start(path, arguments);
connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(badProcess(QProcess::ProcessError)));
qDebug() << "SLOT successfully!" << endl;
}

void MainWindow::badProcess(QProcess::ProcessError error)
{
qDebug() << "Process error!!" << error;
}

in this application, I want to run the other applications through click the buttons in the QMainWindow.

faldzip
26th April 2009, 18:55
as for me you should use qobject_cast instead of static_cast and then check if QToolButton * sender is NULL or not. Next thing is that you can change the key with value in map - that would make starting app much simpler. Here is my code doing similar thing. Check if it is not crashing or tell me what should I do to crash it :]


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileInfo>
#include <QFileIconProvider>
#include <QIcon>
#include <QFileDialog>
#include <QProcess>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_actionAdd_application_triggered()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Choose the application"), qApp->applicationDirPath(), tr("Excutable(*.exe)"));
if(filename.isNull())
return;

QFileInfo fileInfo(filename);
QFileIconProvider seekIcon;
QIcon icon = seekIcon.icon(fileInfo);
QToolButton *btn = new QToolButton;
btn->resize( 300, 300);
btn->setIcon(icon);

connect(btn, SIGNAL(clicked()), SLOT(slotExecute()));
m_map.insert(btn, filename);
ui->verticalLayout_2->addWidget(btn);
}

void MainWindow::slotExecute()
{
QToolButton * btn = qobject_cast<QToolButton *>(sender());
if (!btn)
return;

QString filename = m_map.value(btn);
QProcess::startDetached(filename);
}

sophister
27th April 2009, 06:30
Thanks!! Uh, I am wondering if it is not suitable to use the C++ static_cast<> or daynamic_cast<>. I am wondering what's the difference between them two and the qobject_cast<>.
Next thing is, I do not think it is necessary in the
void MainWindow::slotExecute() to check if the sender is NULL, because if there is no sender, this SLOT won't be called, right?

spirit
27th April 2009, 06:40
Next thing is, I do not think it is necessary in the
void MainWindow::slotExecute() to check if the sender is NULL, because if there is no sender, this SLOT won't be called, right?
you can call this slot by yourself somwhere in your code, so this check is needed.
note:


...Slots are normal C++ functions and can be called normally; their only special feature is that signals can be connected to them.

spirit
27th April 2009, 06:43
Thanks!! Uh, I am wondering if it is not suitable to use the C++ static_cast<> or daynamic_cast<>. I am wondering what's the difference between them two and the qobject_cast<>.

qobject_cast is using meta information for correct casting of Qt's objects.
read this (http://doc.trolltech.com/4.5/qobject.html#qobject_cast) for more info.

sophister
27th April 2009, 06:53
Yeah!!
I have found the mistake!!
It hides in the following code:

QMapIterator<QString, QToolButton *> i(buttons);
while(i.hasNext())
{
if(i.peekNext().value() == sender)
{
path = i.next().key();
qDebug() << "Find the path!!\n";
break;
}
}
if the first value in the iterator does not equals the sender, the loop will continue forever!! So the solution is to add such code as:

QMapIterator<QString, QToolButton *> i(buttons);
while(i.hasNext())
{
// qDebug() << "Enter the while loop successfully!";
if(i.peekNext().value() == sender)
{
path = i.next().key();
qDebug() << "Find the path!!\n";
break;
}
else
{
i.next(); // without this, the loop may continue forever!!!!!
}
}


But I've got another question, following is your code to start another application:

QProcess::startDetached(filename);

Are there some different effects between your way and mine? The following is my way to start it:

QStringList arguments;
arguments << "-style" << "motif";
QProcess *myProcess = new QProcess(this);
myProcess->start(path, arguments);

Thanks a lot!!

sophister
27th April 2009, 07:01
yes, you are right. I forgot that it can be called somewhere by I.
thanks

sophister
27th April 2009, 07:06
So I think it will work if I use the ISO C++ dynamic_cast or static_cast.
The doc says the qobject_cast does not require RTTI.
what do you think is not suitable if we use dynamic_cast or static_cast?
By the way, you get up so early!!

spirit
27th April 2009, 07:09
So I think it will work if I use the ISO C++ dynamic_cast or static_cast.
The doc says the qobject_cast does not require RTTI.
what do you think is not suitable if we use dynamic_cast or static_cast?

for objects which inherit from QObject it's better to use qobject_cast.


By the way, you get up so early!!
my local time is 09:09 am :)

sophister
27th April 2009, 07:18
Thanks.
I thought your local time is six o'clock.
uh, my local time is 2 : 15 p.m.:)

spirit
27th April 2009, 07:32
But I've got another question, following is your code to start another application:

QProcess::startDetached(filename);

in this case a process will start as


Unix: The started process will run in its own session and act like a daemon.

Windows: Arguments that contain spaces are wrapped in quotes. The started process will run as a regular standalone process.


in this case


Are there some different effects between your way and mine? The following is my way to start it:

QStringList arguments;
arguments << "-style" << "motif";
QProcess *myProcess = new QProcess(this);
myProcess->start(path, arguments);

Thanks a lot!!
you don't lose communication with a process, i.e. you can handle signals readyReadStandardError, readyReadStandardOutput etc.
so, if you don't need to process signals then you can use only static methods for starting processes.

sophister
27th April 2009, 07:39
Oh, I see.
thank you, very very much!!