Завершение QProcess в деструкторе - PullRequest
0 голосов
/ 04 мая 2018

У меня проблема при попытке остановить мой QProcess в родительском деструкторе. Вот мой код:

AbstractProcess::~AbstractProcess()
{
    if((m_process->state() == QProcess::Running)
       || (m_process->state() == QProcess::Starting))
    {
        m_process->terminate();
        m_process->waitForFinished();
    }
}

m_process - указатель на QProcess. В конструкторе AbstractProcess у меня есть этот код:

 m_process = new QProcess(this);

Итак, когда AbstractProcess удалено, я получаю к нему деструктор, и у меня возникает ошибка сегментации:

m_process->waitForFinished();

Кто-нибудь может сказать мне, в чем моя ошибка?

UPD : Как было сказано ниже в комментариях, проблема была не в коде, который я предоставил. Очень сожалею об этом. Поэтому я постараюсь объяснить, в чем проблема. Может быть, это кому-нибудь поможет. AbstractProcess Как можно догадаться по названию, это абстрактный класс. Так что у него есть чисто виртуальные функции. На них стоит:

virtual void onProcessFinished(int exitCode, QProcess::ExitStatus
exitStatus) = 0;

Полное тело моего конструктора:

m_process = new QProcess(this);
connect(m_process,static_cast<void(QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
        this, &AbstractProcess::onProcessFinished);

И теперь очевидно, что при вызове waitForFinished процесс выдает сигнал finished и вызывается чисто виртуальная функция. Это приводит к неопределенному поведению. Чтобы это исправить, я звоню disconnect перед тем, как остановить процесс. Деструктор теперь выглядит так:

AbstractProcess::~AbstractProcess()
{
    disconnect(m_process,static_cast<void(QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
               this, &AbstractProcess::onProcessFinished)        
    if((m_process->state() == QProcess::Running)
       || (m_process->state() == QProcess::Starting))
    {
        m_process->terminate();
        m_process->waitForFinished();
    }
}

Спасибо всем за помощь.

1 Ответ

0 голосов
/ 04 мая 2018

Когда вы сначала вызываете m_process->terminate();, нет никакой гарантии, что процесс выйдет .., однако нет гарантии, что процесс продолжит существовать из-за вызова ( WM_CLOSE в windows / SIGTERM в Linux), поэтому вызов m_process->waitForFinished(); в процессе, который, возможно, уже завершился, может вызвать ошибку сегментации. правильный и безопасный подход - делать правильные вещи по порядку:

  m_process->waitForFinished();
  m_process->terminate();
...