4

I have a qt GUI application which contains a widget DS9 derived from a QFrame, for opening and operating with an external program. The implementation of the class looks like this:

ds9.h

#ifndef DS9_H
#define DS9_H

#include <QFrame>
#include <QProcess>

class DS9 : public QFrame
{
    Q_OBJECT

public:
    explicit DS9(QWidget *parent = 0);
    ~DS9();  

signals:


public slots:
    void runDS9();

private:
    QProcess *ds9;
};

#endif // DS9_H

ds9.cpp

DS9::DS9(QWidget *parent):
    QFrame(parent)
{
    ds9 = new QProcess();
    ds9->setProgram("ds9");
    QStringList arguments;
    arguments << "-invert" << "-zscale";
    ds9->setArguments(arguments);
}

DS9::~DS9()
{
    delete ds9;
}

void DS9::runDS9()
{
    ds9->start();
}

However, when running the program, instead of showing the GUI, a black (not blank) window appears and crashes immediately. The error message looks like the following:

*** Error in `./lightcurve_examiner': double free or corruption (out):        0x00000000013f0610 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x77a8d)[0x7f0a9dcada8d]
/lib64/libc.so.6(cfree+0x5cd)[0x7f0a9dcb9d2d]
/lib64  /libQt5Core.so.5(_ZN23QCoreApplicationPrivate16sendPostedEventsEP7QObjectiP11Q    ThreadData+0x2d0)[0x7f0a9efd0a20]
/lib64/libQt5Core.so.5(+0x2d9983)[0x7f0a9f024983]
/lib64/libglib-2.0.so.0(g_main_context_dispatch+0x15a)[0x7f0a9d2eca8a]
/lib64/libglib-2.0.so.0(+0x49e20)[0x7f0a9d2ece20]
/lib64/libglib-2.0.so.0(g_main_context_iteration+0x2c)[0x7f0a9d2ececc]
.....

However, if I don't set QProcess *ds9 as a member of the class, i.e., do something like this:

in .h:

...
    private:
      //  QProcess *ds9;
...

in .cpp:

void DS9::runDS9()
{
    QProcess * ds9 = new QProcess();
    ds9->setProgram("ds9");
    QStringList arguments;
    arguments << "-invert" << "-zscale";
    ds9->setArguments(arguments);
    ds9->start();
}

everything works fine, i.e., the GUI starts normally, and by calling the slot, the program is correctly invoked.

My question is, why I cannot put the QProcess object as the member of the class? If indeed so, how can I keep the pointer and access/reuse it?

Thank you!

Jerry Ma
  • 511
  • 4
  • 15
  • 4
    The only difference I see is that one time you delete and one time you do not delete the process object. Maybe put a `ds9->waitForFinished()` in front of delete, because delete terminates the process and you might want to wait until it exits voluntarily. Can you please produce a simple example app I can run myself to check out the errors. – Ronny Brendel Sep 02 '15 at 06:48
  • Try to get a better backtrace with full debug information. – Frank Osterfeld Sep 02 '15 at 08:08
  • 1
    Remove your build folder, build the project again, and see if it works. If it still doesn't, then you're creating the `DS9` instance before `QApplication` is constructed, perhaps? – Kuba hasn't forgotten Monica Sep 02 '15 at 15:14
  • Thank you Kuba. Rebuild the project works!! I never expected this could be the issue. – Jerry Ma Sep 04 '15 at 16:25

1 Answers1

1

To me, it looks like there might be a problem with the lifetime of your DS9 object, i.e. it is being deleted too soon and so the problem with your code is external to your class. I had the very same problem the other day and the problem was to do with my scrappy testing code that created a QProcess that was deleted before calling QApplication::exec(). I would recommend, if you've not already tried this, that you derive a class from QProcess and add a logging call to its destructor and to the destructor of DS9, or see if you can add breakpoints in these destructors and look at the flow of your program externally. Also, as an extra point, you might want to change your constructor call to QProcess to add the DS9 object as a parent, which will save you from having to call delete manually in the destructor of DS9.

Good luck :)

stellarpower
  • 332
  • 3
  • 13